00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <QDockWidget>
00027 # include <QMessageBox>
00028 #endif
00029
00030 #include "DlgEvaluateMeshImp.h"
00031
00032 #include <boost/signals.hpp>
00033 #include <boost/bind.hpp>
00034
00035 #include <Base/Interpreter.h>
00036 #include <Base/Sequencer.h>
00037 #include <Gui/Application.h>
00038 #include <Gui/Command.h>
00039 #include <Gui/Document.h>
00040 #include <Gui/DockWindowManager.h>
00041 #include <Gui/MainWindow.h>
00042 #include <Gui/WaitCursor.h>
00043 #include <Gui/View3DInventor.h>
00044 #include <Gui/View3DInventorViewer.h>
00045
00046 #include <Mod/Mesh/App/Core/Evaluation.h>
00047 #include <Mod/Mesh/App/Core/Degeneration.h>
00048 #include <Mod/Mesh/App/MeshFeature.h>
00049 #include <Mod/Mesh/App/FeatureMeshDefects.h>
00050 #include "ViewProviderDefects.h"
00051
00052 using namespace MeshCore;
00053 using namespace Mesh;
00054 using namespace MeshGui;
00055
00056 CleanupHandler::CleanupHandler()
00057 : QObject(qApp)
00058 {
00059
00060 connect(qApp, SIGNAL(lastWindowClosed()), this, SLOT(cleanup()));
00061 }
00062
00063
00064
00065 void CleanupHandler::cleanup()
00066 {
00067 DockEvaluateMeshImp::destruct();
00068 }
00069
00070
00071
00072 class DlgEvaluateMeshImp::Private
00073 {
00074 public:
00075 Private() : meshFeature(0), view(0)
00076 {
00077 }
00078 ~Private()
00079 {
00080 }
00081
00082 std::map<std::string, ViewProviderMeshDefects*> vp;
00083 Mesh::Feature* meshFeature;
00084 QPointer<Gui::View3DInventor> view;
00085 std::vector<unsigned long> self_intersections;
00086 };
00087
00088
00089
00090 void DlgEvaluateMeshImp::changeEvent(QEvent *e)
00091 {
00092 if (e->type() == QEvent::LanguageChange) {
00093 this->retranslateUi(this);
00094 meshNameButton->setItemText(0, tr("No selection"));
00095 }
00096 QDialog::changeEvent(e);
00097 }
00098
00099 void DlgEvaluateMeshImp::slotCreatedObject(const App::DocumentObject& Obj)
00100 {
00101
00102 if (Obj.getTypeId().isDerivedFrom(Mesh::Feature::getClassTypeId())) {
00103 QString label = QString::fromUtf8(Obj.Label.getValue());
00104 QString name = QString::fromAscii(Obj.getNameInDocument());
00105 meshNameButton->addItem(label, name);
00106 }
00107 }
00108
00109 void DlgEvaluateMeshImp::slotDeletedObject(const App::DocumentObject& Obj)
00110 {
00111
00112 if (Obj.getTypeId().isDerivedFrom(Mesh::Feature::getClassTypeId())) {
00113 int index = meshNameButton->findData(QString::fromAscii(Obj.getNameInDocument()));
00114 if (index > 0) {
00115 meshNameButton->removeItem(index);
00116 meshNameButton->setDisabled(meshNameButton->count() < 2);
00117 }
00118 }
00119
00120
00121 if (&Obj == d->meshFeature) {
00122 removeViewProviders();
00123 d->meshFeature = 0;
00124 meshNameButton->setCurrentIndex(0);
00125 cleanInformation();
00126 d->self_intersections.clear();
00127 }
00128 }
00129
00130 void DlgEvaluateMeshImp::slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop)
00131 {
00132
00133 if (&Obj == d->meshFeature && Prop.getTypeId() == Mesh::PropertyMeshKernel::getClassTypeId()) {
00134 removeViewProviders();
00135 cleanInformation();
00136 showInformation();
00137 d->self_intersections.clear();
00138 }
00139 else if (Obj.getTypeId().isDerivedFrom(Mesh::Feature::getClassTypeId())) {
00140
00141 if (Prop.getTypeId() == App::PropertyString::getClassTypeId() &&
00142 strcmp(Prop.getName(), "Label") == 0) {
00143 QString label = QString::fromUtf8(Obj.Label.getValue());
00144 QString name = QString::fromAscii(Obj.getNameInDocument());
00145 int index = meshNameButton->findData(name);
00146 meshNameButton->setItemText(index, label);
00147 }
00148 }
00149 }
00150
00151 void DlgEvaluateMeshImp::slotCreatedDocument(const App::Document& Doc)
00152 {
00153 }
00154
00155 void DlgEvaluateMeshImp::slotDeletedDocument(const App::Document& Doc)
00156 {
00157 if (&Doc == getDocument()) {
00158
00159 for (std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.begin(); it != d->vp.end(); ++it) {
00160 delete it->second;
00161 }
00162
00163 d->vp.clear();
00164
00165
00166 this->detachDocument();
00167 d->view = 0;
00168 on_refreshButton_clicked();
00169 }
00170 }
00171
00179 DlgEvaluateMeshImp::DlgEvaluateMeshImp(QWidget* parent, Qt::WFlags fl)
00180 : QDialog(parent, fl), d(new Private())
00181 {
00182 this->setupUi(this);
00183 line->setFrameShape(QFrame::HLine);
00184 line->setFrameShadow(QFrame::Sunken);
00185 line_2->setFrameShape(QFrame::HLine);
00186 line_2->setFrameShadow(QFrame::Sunken);
00187 line_3->setFrameShape(QFrame::HLine);
00188 line_3->setFrameShadow(QFrame::Sunken);
00189 line_4->setFrameShape(QFrame::HLine);
00190 line_4->setFrameShadow(QFrame::Sunken);
00191 line_5->setFrameShape(QFrame::HLine);
00192 line_5->setFrameShadow(QFrame::Sunken);
00193 line_6->setFrameShape(QFrame::HLine);
00194 line_6->setFrameShadow(QFrame::Sunken);
00195 line_7->setFrameShape(QFrame::HLine);
00196 line_7->setFrameShadow(QFrame::Sunken);
00197 line_8->setFrameShape(QFrame::HLine);
00198 line_8->setFrameShadow(QFrame::Sunken);
00199
00200 connect(buttonHelp, SIGNAL (clicked()),
00201 Gui::getMainWindow(), SLOT (whatsThis()));
00202
00203
00204 this->on_refreshButton_clicked();
00205 }
00206
00210 DlgEvaluateMeshImp::~DlgEvaluateMeshImp()
00211 {
00212
00213 for (std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.begin(); it != d->vp.end(); ++it) {
00214 if (d->view)
00215 d->view->getViewer()->removeViewProvider(it->second);
00216 delete it->second;
00217 }
00218
00219 d->vp.clear();
00220 delete d;
00221 }
00222
00223 void DlgEvaluateMeshImp::setMesh(Mesh::Feature* m)
00224 {
00225 App::Document* doc = m->getDocument();
00226 if (doc != getDocument())
00227 attachDocument(doc);
00228
00229 refreshList();
00230
00231 int ct = meshNameButton->count();
00232 QString objName = QString::fromAscii(m->getNameInDocument());
00233 for (int i=1; i<ct; i++) {
00234 if (meshNameButton->itemData(i).toString() == objName) {
00235 meshNameButton->setCurrentIndex(i);
00236 on_meshNameButton_activated(i);
00237 break;
00238 }
00239 }
00240 }
00241
00242 void DlgEvaluateMeshImp::addViewProvider(const char* name, const std::vector<unsigned long>& indices)
00243 {
00244 removeViewProvider(name);
00245
00246 if (d->view) {
00247 ViewProviderMeshDefects* vp = static_cast<ViewProviderMeshDefects*>(Base::Type::createInstanceByName(name));
00248 assert(vp->getTypeId().isDerivedFrom(Gui::ViewProvider::getClassTypeId()));
00249 vp->attach(d->meshFeature);
00250 d->view->getViewer()->addViewProvider( vp );
00251 vp->showDefects(indices);
00252 d->vp[name] = vp;
00253 }
00254 }
00255
00256 void DlgEvaluateMeshImp::removeViewProvider(const char* name)
00257 {
00258 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find(name);
00259 if (it != d->vp.end()) {
00260 if (d->view)
00261 d->view->getViewer()->removeViewProvider(it->second);
00262 delete it->second;
00263 d->vp.erase(it);
00264 }
00265 }
00266
00267 void DlgEvaluateMeshImp::removeViewProviders()
00268 {
00269 for (std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.begin(); it != d->vp.end(); ++it) {
00270 if (d->view)
00271 d->view->getViewer()->removeViewProvider(it->second);
00272 delete it->second;
00273 }
00274 d->vp.clear();
00275 }
00276
00277 void DlgEvaluateMeshImp::on_meshNameButton_activated(int i)
00278 {
00279 QString item = meshNameButton->itemData(i).toString();
00280
00281 d->meshFeature = 0;
00282 std::vector<App::DocumentObject*> objs = getDocument()->getObjectsOfType(Mesh::Feature::getClassTypeId());
00283 for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
00284 if (item == QLatin1String((*it)->getNameInDocument())) {
00285 d->meshFeature = (Mesh::Feature*)(*it);
00286 break;
00287 }
00288 }
00289
00290 if (i== 0) {
00291 cleanInformation();
00292 }
00293 else {
00294 showInformation();
00295 }
00296 }
00297
00298 void DlgEvaluateMeshImp::refreshList()
00299 {
00300 QList<QPair<QString, QString> > items;
00301 if (this->getDocument()) {
00302 std::vector<App::DocumentObject*> objs = this->getDocument()->getObjectsOfType(Mesh::Feature::getClassTypeId());
00303 for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
00304 items.push_back(qMakePair(QString::fromUtf8((*it)->Label.getValue()),
00305 QString::fromAscii((*it)->getNameInDocument())));
00306 }
00307 }
00308
00309 meshNameButton->clear();
00310 meshNameButton->addItem(tr("No selection"));
00311 for (QList<QPair<QString, QString> >::iterator it = items.begin(); it != items.end(); ++it)
00312 meshNameButton->addItem(it->first, it->second);
00313 meshNameButton->setDisabled(items.empty());
00314 cleanInformation();
00315 }
00316
00317 void DlgEvaluateMeshImp::showInformation()
00318 {
00319 analyzeOrientationButton->setEnabled(true);
00320 analyzeDuplicatedFacesButton->setEnabled(true);
00321 analyzeDuplicatedPointsButton->setEnabled(true);
00322 analyzeNonmanifoldsButton->setEnabled(true);
00323 analyzeDegeneratedButton->setEnabled(true);
00324 analyzeIndicesButton->setEnabled(true);
00325 analyzeSelfIntersectionButton->setEnabled(true);
00326 analyzeFoldsButton->setEnabled(true);
00327 analyzeAllTogether->setEnabled(true);
00328
00329 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00330 textLabel4->setText(QString::fromAscii("%1").arg(rMesh.CountFacets()));
00331 textLabel5->setText(QString::fromAscii("%1").arg(rMesh.CountEdges()));
00332 textLabel6->setText(QString::fromAscii("%1").arg(rMesh.CountPoints()));
00333 }
00334
00335 void DlgEvaluateMeshImp::cleanInformation()
00336 {
00337 textLabel4->setText( tr("No information") );
00338 textLabel5->setText( tr("No information") );
00339 textLabel6->setText( tr("No information") );
00340 checkOrientationButton->setText( tr("No information") );
00341 checkDuplicatedFacesButton->setText( tr("No information") );
00342 checkDuplicatedPointsButton->setText( tr("No information") );
00343 checkNonmanifoldsButton->setText( tr("No information") );
00344 checkDegenerationButton->setText( tr("No information") );
00345 checkIndicesButton->setText( tr("No information") );
00346 checkSelfIntersectionButton->setText( tr("No information") );
00347 checkFoldsButton->setText( tr("No information") );
00348 analyzeOrientationButton->setDisabled(true);
00349 repairOrientationButton->setDisabled(true);
00350 analyzeDuplicatedFacesButton->setDisabled(true);
00351 repairDuplicatedFacesButton->setDisabled(true);
00352 analyzeDuplicatedPointsButton->setDisabled(true);
00353 repairDuplicatedPointsButton->setDisabled(true);
00354 analyzeNonmanifoldsButton->setDisabled(true);
00355 repairNonmanifoldsButton->setDisabled(true);
00356 analyzeDegeneratedButton->setDisabled(true);
00357 repairDegeneratedButton->setDisabled(true);
00358 analyzeIndicesButton->setDisabled(true);
00359 repairIndicesButton->setDisabled(true);
00360 analyzeSelfIntersectionButton->setDisabled(true);
00361 repairSelfIntersectionButton->setDisabled(true);
00362 analyzeFoldsButton->setDisabled(true);
00363 repairFoldsButton->setDisabled(true);
00364 analyzeAllTogether->setDisabled(true);
00365 repairAllTogether->setDisabled(true);
00366 }
00367
00368 void DlgEvaluateMeshImp::on_refreshButton_clicked()
00369 {
00370
00371 Gui::Document* gui = Gui::Application::Instance->activeDocument();
00372 if (gui) {
00373 App::Document* doc = gui->getDocument();
00374
00375
00376 if (doc && doc != this->getDocument()) {
00377 attachDocument(doc);
00378 removeViewProviders();
00379 d->view = dynamic_cast<Gui::View3DInventor*>(gui->getActiveView());
00380 }
00381 }
00382
00383 refreshList();
00384 }
00385
00386 void DlgEvaluateMeshImp::on_checkOrientationButton_clicked()
00387 {
00388 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshOrientation");
00389 if (it != d->vp.end()) {
00390 if (checkOrientationButton->isChecked())
00391 it->second->show();
00392 else
00393 it->second->hide();
00394 }
00395 }
00396
00397 void DlgEvaluateMeshImp::on_analyzeOrientationButton_clicked()
00398 {
00399 if (d->meshFeature) {
00400 analyzeOrientationButton->setEnabled(false);
00401 qApp->processEvents();
00402 qApp->setOverrideCursor(Qt::WaitCursor);
00403
00404 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00405 MeshEvalOrientation eval(rMesh);
00406 std::vector<unsigned long> inds = eval.GetIndices();
00407 if (inds.empty() && !eval.Evaluate()) {
00408 checkOrientationButton->setText(tr("Flipped normals found"));
00409 MeshEvalFoldOversOnSurface f_eval(rMesh);
00410 if (!f_eval.Evaluate()) {
00411 qApp->restoreOverrideCursor();
00412 QMessageBox::warning(this, tr("Orientation"),
00413 tr("Check failed due to folds on the surface.\n"
00414 "Please run the command to repair folds first"));
00415 qApp->setOverrideCursor(Qt::WaitCursor);
00416 }
00417 }
00418 else if (inds.empty()) {
00419 checkOrientationButton->setText( tr("No flipped normals") );
00420 checkOrientationButton->setChecked(false);
00421 repairOrientationButton->setEnabled(false);
00422 removeViewProvider( "MeshGui::ViewProviderMeshOrientation" );
00423 }
00424 else {
00425 checkOrientationButton->setText( tr("%1 flipped normals").arg(inds.size()) );
00426 checkOrientationButton->setChecked(true);
00427 repairOrientationButton->setEnabled(true);
00428 repairAllTogether->setEnabled(true);
00429 addViewProvider( "MeshGui::ViewProviderMeshOrientation", eval.GetIndices());
00430 }
00431
00432 qApp->restoreOverrideCursor();
00433 analyzeOrientationButton->setEnabled(true);
00434 }
00435 }
00436
00437 void DlgEvaluateMeshImp::on_repairOrientationButton_clicked()
00438 {
00439 if (d->meshFeature) {
00440 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00441 const char* objName = d->meshFeature->getNameInDocument();
00442 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00443 doc->openCommand("Harmonize normals");
00444 try {
00445 Gui::Application::Instance->runCommand(
00446 true, "App.getDocument(\"%s\").getObject(\"%s\").harmonizeNormals()"
00447 , docName, objName);
00448 }
00449 catch (const Base::Exception& e) {
00450 QMessageBox::warning(this, tr("Orientation"), QString::fromLatin1(e.what()));
00451 }
00452
00453 doc->commitCommand();
00454 doc->getDocument()->recompute();
00455
00456 repairOrientationButton->setEnabled(false);
00457 checkOrientationButton->setChecked(false);
00458 removeViewProvider( "MeshGui::ViewProviderMeshOrientation" );
00459 }
00460 }
00461
00462 void DlgEvaluateMeshImp::on_checkNonmanifoldsButton_clicked()
00463 {
00464 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshNonManifolds");
00465 if (it != d->vp.end()) {
00466 if (checkNonmanifoldsButton->isChecked())
00467 it->second->show();
00468 else
00469 it->second->hide();
00470 }
00471 }
00472
00473 void DlgEvaluateMeshImp::on_analyzeNonmanifoldsButton_clicked()
00474 {
00475 if (d->meshFeature) {
00476 analyzeNonmanifoldsButton->setEnabled(false);
00477 qApp->processEvents();
00478 qApp->setOverrideCursor(Qt::WaitCursor);
00479
00480 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00481 MeshEvalTopology eval(rMesh);
00482
00483 if (eval.Evaluate()) {
00484 checkNonmanifoldsButton->setText(tr("No non-manifolds"));
00485 checkNonmanifoldsButton->setChecked(false);
00486 repairNonmanifoldsButton->setEnabled(false);
00487 removeViewProvider("MeshGui::ViewProviderMeshNonManifolds");
00488 }
00489 else {
00490 checkNonmanifoldsButton->setText(tr("%1 non-manifolds").arg(eval.CountManifolds()));
00491 checkNonmanifoldsButton->setChecked(true);
00492 repairNonmanifoldsButton->setEnabled(true);
00493 repairAllTogether->setEnabled(true);
00494 const std::vector<std::pair<unsigned long, unsigned long> >& inds = eval.GetIndices();
00495 std::vector<unsigned long> indices;
00496 indices.reserve(2*inds.size());
00497 std::vector<std::pair<unsigned long, unsigned long> >::const_iterator it;
00498 for (it = inds.begin(); it != inds.end(); ++it) {
00499 indices.push_back(it->first);
00500 indices.push_back(it->second);
00501 }
00502
00503 addViewProvider("MeshGui::ViewProviderMeshNonManifolds", indices);
00504 }
00505
00506 qApp->restoreOverrideCursor();
00507 analyzeNonmanifoldsButton->setEnabled(true);
00508 }
00509 }
00510
00511 void DlgEvaluateMeshImp::on_repairNonmanifoldsButton_clicked()
00512 {
00513 if (d->meshFeature) {
00514 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00515 const char* objName = d->meshFeature->getNameInDocument();
00516 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00517 doc->openCommand("Remove non-manifolds");
00518 try {
00519 Gui::Application::Instance->runCommand(
00520 true, "App.getDocument(\"%s\").getObject(\"%s\").removeNonManifolds()"
00521 , docName, objName);
00522 }
00523 catch (const Base::Exception& e) {
00524 QMessageBox::warning(this, tr("Non-manifolds"), QString::fromLatin1(e.what()));
00525 }
00526 catch (...) {
00527 QMessageBox::warning(this, tr("Non-manifolds"), tr("Cannot remove non-manifolds"));
00528 }
00529
00530 doc->commitCommand();
00531 doc->getDocument()->recompute();
00532
00533 repairNonmanifoldsButton->setEnabled(false);
00534 checkNonmanifoldsButton->setChecked(false);
00535 removeViewProvider("MeshGui::ViewProviderMeshNonManifolds");
00536 }
00537 }
00538
00539 void DlgEvaluateMeshImp::on_checkIndicesButton_clicked()
00540 {
00541 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshIndices");
00542 if (it != d->vp.end()) {
00543 if (checkIndicesButton->isChecked())
00544 it->second->show();
00545 else
00546 it->second->hide();
00547 }
00548 }
00549
00550 void DlgEvaluateMeshImp::on_analyzeIndicesButton_clicked()
00551 {
00552 if (d->meshFeature) {
00553 analyzeIndicesButton->setEnabled(false);
00554 qApp->processEvents();
00555 qApp->setOverrideCursor(Qt::WaitCursor);
00556
00557 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00558 MeshEvalRangeFacet rf(rMesh);
00559 MeshEvalRangePoint rp(rMesh);
00560 MeshEvalCorruptedFacets cf(rMesh);
00561 MeshEvalNeighbourhood nb(rMesh);
00562
00563 if (!rf.Evaluate()) {
00564 checkIndicesButton->setText(tr("Invalid face indices"));
00565 checkIndicesButton->setChecked(true);
00566 repairIndicesButton->setEnabled(true);
00567 repairAllTogether->setEnabled(true);
00568 addViewProvider("MeshGui::ViewProviderMeshIndices", rf.GetIndices());
00569 }
00570 else if (!rp.Evaluate()) {
00571 checkIndicesButton->setText(tr("Invalid point indices"));
00572 checkIndicesButton->setChecked(true);
00573 repairIndicesButton->setEnabled(true);
00574 repairAllTogether->setEnabled(true);
00575
00576 }
00577 else if (!cf.Evaluate()) {
00578 checkIndicesButton->setText(tr("Multiple point indices"));
00579 checkIndicesButton->setChecked(true);
00580 repairIndicesButton->setEnabled(true);
00581 repairAllTogether->setEnabled(true);
00582 addViewProvider("MeshGui::ViewProviderMeshIndices", cf.GetIndices());
00583 }
00584 else if (!nb.Evaluate()) {
00585 checkIndicesButton->setText(tr("Invalid neighbour indices"));
00586 checkIndicesButton->setChecked(true);
00587 repairIndicesButton->setEnabled(true);
00588 repairAllTogether->setEnabled(true);
00589 addViewProvider("MeshGui::ViewProviderMeshIndices", nb.GetIndices());
00590 }
00591 else {
00592 checkIndicesButton->setText(tr("No invalid indices"));
00593 checkIndicesButton->setChecked(false);
00594 repairIndicesButton->setEnabled(false);
00595 removeViewProvider("MeshGui::ViewProviderMeshIndices");
00596 }
00597
00598 qApp->restoreOverrideCursor();
00599 analyzeIndicesButton->setEnabled(true);
00600 }
00601 }
00602
00603 void DlgEvaluateMeshImp::on_repairIndicesButton_clicked()
00604 {
00605 if (d->meshFeature) {
00606 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00607 const char* objName = d->meshFeature->getNameInDocument();
00608 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00609 doc->openCommand("Fix indices");
00610 try {
00611 Gui::Application::Instance->runCommand(
00612 true, "App.getDocument(\"%s\").getObject(\"%s\").fixIndices()"
00613 , docName, objName);
00614 }
00615 catch (const Base::Exception& e) {
00616 QMessageBox::warning(this, tr("Indices"), QString::fromLatin1(e.what()));
00617 }
00618
00619 doc->commitCommand();
00620 doc->getDocument()->recompute();
00621
00622 repairIndicesButton->setEnabled(false);
00623 checkIndicesButton->setChecked(false);
00624 removeViewProvider("MeshGui::ViewProviderMeshIndices");
00625 }
00626 }
00627
00628 void DlgEvaluateMeshImp::on_checkDegenerationButton_clicked()
00629 {
00630 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshDegenerations");
00631 if (it != d->vp.end()) {
00632 if (checkDegenerationButton->isChecked())
00633 it->second->show();
00634 else
00635 it->second->hide();
00636 }
00637 }
00638
00639 void DlgEvaluateMeshImp::on_analyzeDegeneratedButton_clicked()
00640 {
00641 if (d->meshFeature) {
00642 analyzeDegeneratedButton->setEnabled(false);
00643 qApp->processEvents();
00644 qApp->setOverrideCursor(Qt::WaitCursor);
00645
00646 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00647 MeshEvalDegeneratedFacets eval(rMesh);
00648 std::vector<unsigned long> degen = eval.GetIndices();
00649
00650 if (degen.empty()) {
00651 checkDegenerationButton->setText(tr("No degenerations"));
00652 checkDegenerationButton->setChecked(false);
00653 repairDegeneratedButton->setEnabled(false);
00654 removeViewProvider("MeshGui::ViewProviderMeshDegenerations");
00655 }
00656 else {
00657 checkDegenerationButton->setText(tr("%1 degenerated faces").arg(degen.size()));
00658 checkDegenerationButton->setChecked(true);
00659 repairDegeneratedButton->setEnabled(true);
00660 repairAllTogether->setEnabled(true);
00661 addViewProvider("MeshGui::ViewProviderMeshDegenerations", degen);
00662 }
00663
00664 qApp->restoreOverrideCursor();
00665 analyzeDegeneratedButton->setEnabled(true);
00666 }
00667 }
00668
00669 void DlgEvaluateMeshImp::on_repairDegeneratedButton_clicked()
00670 {
00671 if (d->meshFeature) {
00672 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00673 const char* objName = d->meshFeature->getNameInDocument();
00674 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00675 doc->openCommand("Remove degenerated faces");
00676 try {
00677 Gui::Application::Instance->runCommand(
00678 true, "App.getDocument(\"%s\").getObject(\"%s\").fixDegenerations()"
00679 , docName, objName);
00680 }
00681 catch (const Base::Exception& e) {
00682 QMessageBox::warning(this, tr("Degenerations"), QString::fromLatin1(e.what()));
00683 }
00684
00685 doc->commitCommand();
00686 doc->getDocument()->recompute();
00687
00688 repairDegeneratedButton->setEnabled(false);
00689 checkDegenerationButton->setChecked(false);
00690 removeViewProvider("MeshGui::ViewProviderMeshDegenerations");
00691 }
00692 }
00693
00694 void DlgEvaluateMeshImp::on_checkDuplicatedFacesButton_clicked()
00695 {
00696 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshDuplicatedFaces");
00697 if (it != d->vp.end()) {
00698 if (checkDuplicatedFacesButton->isChecked())
00699 it->second->show();
00700 else
00701 it->second->hide();
00702 }
00703 }
00704
00705 void DlgEvaluateMeshImp::on_analyzeDuplicatedFacesButton_clicked()
00706 {
00707 if (d->meshFeature) {
00708 analyzeDuplicatedFacesButton->setEnabled(false);
00709 qApp->processEvents();
00710 qApp->setOverrideCursor(Qt::WaitCursor);
00711
00712 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00713 MeshEvalDuplicateFacets eval(rMesh);
00714 std::vector<unsigned long> dupl = eval.GetIndices();
00715
00716 if (dupl.empty()) {
00717 checkDuplicatedFacesButton->setText(tr("No duplicated faces"));
00718 checkDuplicatedFacesButton->setChecked(false);
00719 repairDuplicatedFacesButton->setEnabled(false);
00720 removeViewProvider("MeshGui::ViewProviderMeshDuplicatedFaces");
00721 }
00722 else {
00723 checkDuplicatedFacesButton->setText(tr("%1 duplicated faces").arg(dupl.size()));
00724 checkDuplicatedFacesButton->setChecked(true);
00725 repairDuplicatedFacesButton->setEnabled(true);
00726 repairAllTogether->setEnabled(true);
00727
00728 addViewProvider("MeshGui::ViewProviderMeshDuplicatedFaces", dupl);
00729 }
00730
00731 qApp->restoreOverrideCursor();
00732 analyzeDuplicatedFacesButton->setEnabled(true);
00733 }
00734 }
00735
00736 void DlgEvaluateMeshImp::on_repairDuplicatedFacesButton_clicked()
00737 {
00738 if (d->meshFeature) {
00739 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00740 const char* objName = d->meshFeature->getNameInDocument();
00741 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00742 doc->openCommand("Remove duplicated faces");
00743 try {
00744 Gui::Application::Instance->runCommand(
00745 true, "App.getDocument(\"%s\").getObject(\"%s\").removeDuplicatedFacets()"
00746 , docName, objName);
00747 }
00748 catch (const Base::Exception& e) {
00749 QMessageBox::warning(this, tr("Duplicated faces"), QString::fromLatin1(e.what()));
00750 }
00751
00752 doc->commitCommand();
00753 doc->getDocument()->recompute();
00754
00755 repairDuplicatedFacesButton->setEnabled(false);
00756 checkDuplicatedFacesButton->setChecked(false);
00757 removeViewProvider("MeshGui::ViewProviderMeshDuplicatedFaces");
00758 }
00759 }
00760
00761 void DlgEvaluateMeshImp::on_checkDuplicatedPointsButton_clicked()
00762 {
00763 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshDuplicatedPoints");
00764 if (it != d->vp.end()) {
00765 if ( checkDuplicatedPointsButton->isChecked() )
00766 it->second->show();
00767 else
00768 it->second->hide();
00769 }
00770 }
00771
00772 void DlgEvaluateMeshImp::on_analyzeDuplicatedPointsButton_clicked()
00773 {
00774 if (d->meshFeature) {
00775 analyzeDuplicatedPointsButton->setEnabled(false);
00776 qApp->processEvents();
00777 qApp->setOverrideCursor(Qt::WaitCursor);
00778
00779 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00780 MeshEvalDuplicatePoints eval(rMesh);
00781
00782 if (eval.Evaluate()) {
00783 checkDuplicatedPointsButton->setText(tr("No duplicated points"));
00784 checkDuplicatedPointsButton->setChecked(false);
00785 repairDuplicatedPointsButton->setEnabled(false);
00786 removeViewProvider("MeshGui::ViewProviderMeshDuplicatedPoints");
00787 }
00788 else {
00789 checkDuplicatedPointsButton->setText(tr("Duplicated points"));
00790 checkDuplicatedPointsButton->setChecked(true);
00791 repairDuplicatedPointsButton->setEnabled(true);
00792 repairAllTogether->setEnabled(true);
00793 addViewProvider("MeshGui::ViewProviderMeshDuplicatedPoints", eval.GetIndices());
00794 }
00795
00796 qApp->restoreOverrideCursor();
00797 analyzeDuplicatedPointsButton->setEnabled(true);
00798 }
00799 }
00800
00801 void DlgEvaluateMeshImp::on_repairDuplicatedPointsButton_clicked()
00802 {
00803 if (d->meshFeature) {
00804 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00805 const char* objName = d->meshFeature->getNameInDocument();
00806 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00807 doc->openCommand("Remove duplicated points");
00808 try {
00809 Gui::Application::Instance->runCommand(
00810 true, "App.getDocument(\"%s\").getObject(\"%s\").removeDuplicatedPoints()"
00811 , docName, objName);
00812 }
00813 catch (const Base::Exception& e) {
00814 QMessageBox::warning(this, tr("Duplicated points"), QString::fromLatin1(e.what()));
00815 }
00816
00817 doc->commitCommand();
00818 doc->getDocument()->recompute();
00819
00820 repairDuplicatedPointsButton->setEnabled(false);
00821 checkDuplicatedPointsButton->setChecked(false);
00822 removeViewProvider("MeshGui::ViewProviderMeshDuplicatedPoints");
00823 }
00824 }
00825
00826 void DlgEvaluateMeshImp::on_checkSelfIntersectionButton_clicked()
00827 {
00828 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshSelfIntersections");
00829 if (it != d->vp.end()) {
00830 if ( checkSelfIntersectionButton->isChecked() )
00831 it->second->show();
00832 else
00833 it->second->hide();
00834 }
00835 }
00836
00837 void DlgEvaluateMeshImp::on_analyzeSelfIntersectionButton_clicked()
00838 {
00839 if (d->meshFeature) {
00840 analyzeSelfIntersectionButton->setEnabled(false);
00841 qApp->processEvents();
00842 qApp->setOverrideCursor(Qt::WaitCursor);
00843
00844 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00845 MeshEvalSelfIntersection eval(rMesh);
00846 std::vector<std::pair<unsigned long, unsigned long> > intersection;
00847 try {
00848 eval.GetIntersections(intersection);
00849 }
00850 catch (const Base::AbortException&) {
00851 Base::Console().Message("The self-intersection analyse was aborted by the user\n");
00852 }
00853
00854 if (intersection.empty()) {
00855 checkSelfIntersectionButton->setText(tr("No self-intersections"));
00856 checkSelfIntersectionButton->setChecked(false);
00857 repairSelfIntersectionButton->setEnabled(false);
00858 removeViewProvider("MeshGui::ViewProviderMeshSelfIntersections");
00859 }
00860 else {
00861 checkSelfIntersectionButton->setText(tr("Self-intersections"));
00862 checkSelfIntersectionButton->setChecked(true);
00863 repairSelfIntersectionButton->setEnabled(true);
00864 repairAllTogether->setEnabled(true);
00865 std::vector<unsigned long> indices;
00866 indices.reserve(2*intersection.size());
00867 std::vector<std::pair<unsigned long, unsigned long> >::iterator it;
00868 for (it = intersection.begin(); it != intersection.end(); ++it) {
00869 indices.push_back(it->first);
00870 indices.push_back(it->second);
00871 }
00872
00873 addViewProvider("MeshGui::ViewProviderMeshSelfIntersections", indices);
00874 d->self_intersections.swap(indices);
00875 }
00876
00877 qApp->restoreOverrideCursor();
00878 analyzeSelfIntersectionButton->setEnabled(true);
00879 }
00880 }
00881
00882 void DlgEvaluateMeshImp::on_repairSelfIntersectionButton_clicked()
00883 {
00884 if (d->meshFeature) {
00885 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00886 #if 0
00887 const char* objName = d->meshFeature->getNameInDocument();
00888 #endif
00889 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00890 doc->openCommand("Fix self-intersections");
00891 #if 0
00892 try {
00893 Gui::Application::Instance->runCommand(
00894 true, "App.getDocument(\"%s\").getObject(\"%s\").fixSelfIntersections()"
00895 , docName, objName);
00896 }
00897 catch (const Base::Exception& e) {
00898 QMessageBox::warning(this, tr("Self-intersections"), QString::fromLatin1(e.what()));
00899 }
00900 #else
00901 Mesh::MeshObject* mesh = d->meshFeature->Mesh.startEditing();
00902 mesh->removeSelfIntersections(d->self_intersections);
00903 d->meshFeature->Mesh.finishEditing();
00904 #endif
00905
00906 doc->commitCommand();
00907 doc->getDocument()->recompute();
00908
00909 repairSelfIntersectionButton->setEnabled(false);
00910 checkSelfIntersectionButton->setChecked(false);
00911 removeViewProvider("MeshGui::ViewProviderMeshSelfIntersections");
00912 }
00913 }
00914
00915 void DlgEvaluateMeshImp::on_checkFoldsButton_clicked()
00916 {
00917 std::map<std::string, ViewProviderMeshDefects*>::iterator it = d->vp.find("MeshGui::ViewProviderMeshFolds");
00918 if (it != d->vp.end()) {
00919 if (checkFoldsButton->isChecked())
00920 it->second->show();
00921 else
00922 it->second->hide();
00923 }
00924 }
00925
00926 void DlgEvaluateMeshImp::on_analyzeFoldsButton_clicked()
00927 {
00928 if (d->meshFeature) {
00929 analyzeFoldsButton->setEnabled(false);
00930 qApp->processEvents();
00931 qApp->setOverrideCursor(Qt::WaitCursor);
00932
00933 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
00934 MeshEvalFoldsOnSurface s_eval(rMesh);
00935 MeshEvalFoldsOnBoundary b_eval(rMesh);
00936 MeshEvalFoldOversOnSurface f_eval(rMesh);
00937 bool ok1 = s_eval.Evaluate();
00938 bool ok2 = b_eval.Evaluate();
00939 bool ok3 = f_eval.Evaluate();
00940
00941 if (ok1 && ok2 && ok3) {
00942 checkFoldsButton->setText(tr("No folds on surface"));
00943 checkFoldsButton->setChecked(false);
00944 repairFoldsButton->setEnabled(false);
00945 removeViewProvider("MeshGui::ViewProviderMeshFolds");
00946 }
00947 else {
00948 std::vector<unsigned long> inds = f_eval.GetIndices();
00949 std::vector<unsigned long> inds1 = s_eval.GetIndices();
00950 std::vector<unsigned long> inds2 = b_eval.GetIndices();
00951 inds.insert(inds.end(), inds1.begin(), inds1.end());
00952 inds.insert(inds.end(), inds2.begin(), inds2.end());
00953
00954
00955 std::sort(inds.begin(), inds.end());
00956 inds.erase(std::unique(inds.begin(), inds.end()), inds.end());
00957
00958 checkFoldsButton->setText(tr("%1 folds on surface").arg(inds.size()));
00959 checkFoldsButton->setChecked(true);
00960 repairFoldsButton->setEnabled(true);
00961 repairAllTogether->setEnabled(true);
00962 addViewProvider("MeshGui::ViewProviderMeshFolds", inds);
00963 }
00964
00965 qApp->restoreOverrideCursor();
00966 analyzeFoldsButton->setEnabled(true);
00967 }
00968 }
00969
00970 void DlgEvaluateMeshImp::on_repairFoldsButton_clicked()
00971 {
00972 if (d->meshFeature) {
00973 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
00974 const char* objName = d->meshFeature->getNameInDocument();
00975 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
00976 qApp->setOverrideCursor(Qt::WaitCursor);
00977 doc->openCommand("Remove folds");
00978 try {
00979 Gui::Application::Instance->runCommand(
00980 true, "App.getDocument(\"%s\").getObject(\"%s\").removeFoldsOnSurface()"
00981 , docName, objName);
00982 }
00983 catch (const Base::Exception& e) {
00984 QMessageBox::warning(this, tr("Folds"), QString::fromLatin1(e.what()));
00985 }
00986
00987 doc->commitCommand();
00988 doc->getDocument()->recompute();
00989
00990 qApp->restoreOverrideCursor();
00991 repairFoldsButton->setEnabled(false);
00992 checkFoldsButton->setChecked(false);
00993 removeViewProvider("MeshGui::ViewProviderMeshFolds");
00994 }
00995 }
00996
00997 void DlgEvaluateMeshImp::on_analyzeAllTogether_clicked()
00998 {
00999 on_analyzeOrientationButton_clicked();
01000 on_analyzeDuplicatedFacesButton_clicked();
01001 on_analyzeDuplicatedPointsButton_clicked();
01002 on_analyzeNonmanifoldsButton_clicked();
01003 on_analyzeDegeneratedButton_clicked();
01004 on_analyzeIndicesButton_clicked();
01005 on_analyzeSelfIntersectionButton_clicked();
01006 on_analyzeFoldsButton_clicked();
01007 }
01008
01009 void DlgEvaluateMeshImp::on_repairAllTogether_clicked()
01010 {
01011 if (d->meshFeature) {
01012 Gui::WaitCursor wc;
01013 const char* docName = App::GetApplication().getDocumentName(d->meshFeature->getDocument());
01014 const char* objName = d->meshFeature->getNameInDocument();
01015 Gui::Document* doc = Gui::Application::Instance->getDocument(docName);
01016 doc->openCommand("Repair mesh");
01017
01018 bool run = false;
01019 bool self = true;
01020 int max_iter=10;
01021 const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
01022 try {
01023 do {
01024 run = false;
01025 {
01026 MeshEvalSelfIntersection eval(rMesh);
01027 if (self && !eval.Evaluate()) {
01028 Gui::Application::Instance->runCommand(true,
01029 "App.getDocument(\"%s\").getObject(\"%s\").fixSelfIntersections()",
01030 docName, objName);
01031 run = true;
01032 }
01033 else {
01034 self = false;
01035 }
01036 qApp->processEvents();
01037 }
01038 {
01039 MeshEvalFoldsOnSurface s_eval(rMesh);
01040 MeshEvalFoldsOnBoundary b_eval(rMesh);
01041 MeshEvalFoldOversOnSurface f_eval(rMesh);
01042 if (!s_eval.Evaluate() || !b_eval.Evaluate() || !f_eval.Evaluate()) {
01043 Gui::Application::Instance->runCommand(true,
01044 "App.getDocument(\"%s\").getObject(\"%s\").removeFoldsOnSurface()",
01045 docName, objName);
01046 run = true;
01047 }
01048 qApp->processEvents();
01049 }
01050 {
01051 MeshEvalOrientation eval(rMesh);
01052 if (!eval.Evaluate()) {
01053 Gui::Application::Instance->runCommand(true,
01054 "App.getDocument(\"%s\").getObject(\"%s\").harmonizeNormals()",
01055 docName, objName);
01056 run = true;
01057 }
01058 qApp->processEvents();
01059 }
01060 {
01061 MeshEvalTopology eval(rMesh);
01062 if (!eval.Evaluate()) {
01063 Gui::Application::Instance->runCommand(true,
01064 "App.getDocument(\"%s\").getObject(\"%s\").removeNonManifolds()",
01065 docName, objName);
01066 run = true;
01067 }
01068 qApp->processEvents();
01069 }
01070 {
01071 MeshEvalRangeFacet rf(rMesh);
01072 MeshEvalRangePoint rp(rMesh);
01073 MeshEvalCorruptedFacets cf(rMesh);
01074 MeshEvalNeighbourhood nb(rMesh);
01075 if (!rf.Evaluate() || !rp.Evaluate() || !cf.Evaluate() || !nb.Evaluate()) {
01076 Gui::Application::Instance->runCommand(true,
01077 "App.getDocument(\"%s\").getObject(\"%s\").fixIndices()",
01078 docName, objName);
01079 run = true;
01080 }
01081 }
01082 {
01083 MeshEvalDegeneratedFacets eval(rMesh);
01084 if (!eval.Evaluate()) {
01085 Gui::Application::Instance->runCommand(true,
01086 "App.getDocument(\"%s\").getObject(\"%s\").fixDegenerations()",
01087 docName, objName);
01088 run = true;
01089 }
01090 qApp->processEvents();
01091 }
01092 {
01093 MeshEvalDuplicateFacets eval(rMesh);
01094 if (!eval.Evaluate()) {
01095 Gui::Application::Instance->runCommand(true,
01096 "App.getDocument(\"%s\").getObject(\"%s\").removeDuplicatedFacets()",
01097 docName, objName);
01098 run = true;
01099 }
01100 qApp->processEvents();
01101 }
01102 {
01103 MeshEvalDuplicatePoints eval(rMesh);
01104 if (!eval.Evaluate()) {
01105 Gui::Application::Instance->runCommand(true,
01106 "App.getDocument(\"%s\").getObject(\"%s\").removeDuplicatedPoints()",
01107 docName, objName);
01108 run = true;
01109 }
01110 qApp->processEvents();
01111 }
01112 } while(checkRepeatButton->isChecked() && run && (--max_iter > 0));
01113 }
01114 catch (const Base::Exception& e) {
01115 QMessageBox::warning(this, tr("Mesh repair"), QString::fromLatin1(e.what()));
01116 }
01117 catch (...) {
01118 QMessageBox::warning(this, tr("Mesh repair"), QString::fromLatin1("Unknown error occurred."));
01119 }
01120
01121 doc->commitCommand();
01122 doc->getDocument()->recompute();
01123 }
01124 }
01125
01126
01127
01128
01129
01130 #if 0 // needed for Qt's lupdate utility
01131 qApp->translate("QDockWidget", "Evaluate & Repair Mesh");
01132 #endif
01133
01134 DockEvaluateMeshImp* DockEvaluateMeshImp::_instance=0;
01135
01136 DockEvaluateMeshImp* DockEvaluateMeshImp::instance()
01137 {
01138
01139 if(!_instance) {
01140 _instance = new DockEvaluateMeshImp(Gui::getMainWindow());
01141 _instance->setSizeGripEnabled(false);
01142 }
01143
01144 return _instance;
01145 }
01146
01147 void DockEvaluateMeshImp::destruct ()
01148 {
01149 if (_instance != 0) {
01150 DockEvaluateMeshImp *pTmp = _instance;
01151 _instance = 0;
01152 delete pTmp;
01153 }
01154 }
01155
01156 bool DockEvaluateMeshImp::hasInstance()
01157 {
01158 return _instance != 0;
01159 }
01160
01165 DockEvaluateMeshImp::DockEvaluateMeshImp( QWidget* parent, Qt::WFlags fl )
01166 : DlgEvaluateMeshImp( parent, fl )
01167 {
01168
01169 Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
01170
01171 QDockWidget* dw = pDockMgr->addDockWindow("Evaluate & Repair Mesh",
01172 this, Qt::RightDockWidgetArea);
01173
01174 dw->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
01175 dw->show();
01176 }
01177
01181 DockEvaluateMeshImp::~DockEvaluateMeshImp()
01182 {
01183 _instance = 0;
01184 }
01185
01189 void DockEvaluateMeshImp::closeEvent(QCloseEvent* e)
01190 {
01191
01192 Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
01193 pDockMgr->removeDockWindow(this);
01194 }
01195
01199 QSize DockEvaluateMeshImp::sizeHint () const
01200 {
01201 return QSize(371, 579);
01202 }
01203
01204 #include "moc_DlgEvaluateMeshImp.cpp"
01205