From 353e556c7dc6e85df9a155b80e9385fb39aaf5cf Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 27 Mar 2021 01:29:21 +0100 Subject: [PATCH] MeshPart: refactor class Tessellation --- src/Mod/MeshPart/Gui/Tessellation.cpp | 293 +++++++++++++++----------- src/Mod/MeshPart/Gui/Tessellation.h | 8 + 2 files changed, 173 insertions(+), 128 deletions(-) diff --git a/src/Mod/MeshPart/Gui/Tessellation.cpp b/src/Mod/MeshPart/Gui/Tessellation.cpp index 97d3f2addd..cc5822aae0 100644 --- a/src/Mod/MeshPart/Gui/Tessellation.cpp +++ b/src/Mod/MeshPart/Gui/Tessellation.cpp @@ -179,20 +179,8 @@ void Tessellation::changeEvent(QEvent *e) QWidget::changeEvent(e); } -namespace MeshPartGui { -struct ShapeInfo { - App::DocumentObjectT obj; - std::string subname; - - ShapeInfo(const App::DocumentObject *o, const char *s) - : obj(o), subname(s) - {} -}; -} - void Tessellation::on_estimateMaximumEdgeLength_clicked() { - std::list shapeObjects; App::Document* activeDoc = App::GetApplication().getActiveDocument(); if (!activeDoc) { return; @@ -211,7 +199,6 @@ void Tessellation::on_estimateMaximumEdgeLength_clicked() edgeLen = std::max(edgeLen, bbox.LengthX()); edgeLen = std::max(edgeLen, bbox.LengthY()); edgeLen = std::max(edgeLen, bbox.LengthZ()); - shapeObjects.emplace_back(sel.pObject, sel.SubName); } } @@ -220,7 +207,7 @@ void Tessellation::on_estimateMaximumEdgeLength_clicked() bool Tessellation::accept() { - std::list shapeObjects; + std::list shapeObjects; App::Document* activeDoc = App::GetApplication().getActiveDocument(); if (!activeDoc) { QMessageBox::critical(this, windowTitle(), tr("No active document")); @@ -254,113 +241,40 @@ bool Tessellation::accept() // For gmsh the workflow is very different because it uses an executable // and therefore things are asynchronous if (method == Gmsh) { - std::list obj; - for (const auto &info : shapeObjects) { - obj.emplace_back(info.obj, info.subname.c_str()); - } - gmsh->process(activeDoc, obj); + gmsh->process(activeDoc, shapeObjects); return false; } + else { + process(method, activeDoc, shapeObjects); + return doClose; + } +} +void Tessellation::process(int method, App::Document* doc, const std::list& shapeObjects) +{ try { - QString objname, label, subname; Gui::WaitCursor wc; - // Save parameters - if (method == Standard) { - ParameterGrp::handle handle = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Mod/Mesh/Meshing/Standard"); - double value = ui->spinSurfaceDeviation->value().getValue(); - handle->SetFloat("LinearDeflection", value); - double angle = ui->spinAngularDeviation->value().getValue(); - handle->SetFloat("AngularDeflection", angle); - bool relative = ui->relativeDeviation->isChecked(); - handle->SetBool("RelativeLinearDeflection", relative); - } + saveParameters(method); - activeDoc->openTransaction("Meshing"); + doc->openTransaction("Meshing"); for (auto &info : shapeObjects) { - subname = QString::fromLatin1(info.subname.c_str()); - objname = QString::fromLatin1(info.obj.getObjectName().c_str()); + QString subname = QString::fromLatin1(info.getSubName().c_str()); + QString objname = QString::fromLatin1(info.getObjectName().c_str()); - auto obj = info.obj.getObject(); + auto obj = info.getObject(); if (!obj) continue; - auto sobj = obj->getSubObject(info.subname.c_str()); + auto sobj = obj->getSubObject(info.getSubName().c_str()); if (!sobj) continue; sobj = sobj->getLinkedObject(true); if (!sobj) continue; - label = QString::fromUtf8(sobj->Label.getValue()); - auto svp = Base::freecad_dynamic_cast( - Gui::Application::Instance->getViewProvider(sobj)); - QString param; - if (method == Standard) { // Standard - double devFace = ui->spinSurfaceDeviation->value().getValue(); - double devAngle = ui->spinAngularDeviation->value().getValue(); - devAngle = Base::toRadians(devAngle); - bool relative = ui->relativeDeviation->isChecked(); - param = QString::fromLatin1("Shape=__shape__, " - "LinearDeflection=%1, " - "AngularDeflection=%2, " - "Relative=%3") - .arg(devFace) - .arg(devAngle) - .arg(relative ? QString::fromLatin1("True") : QString::fromLatin1("False")); - if (ui->meshShapeColors->isChecked()) - param += QString::fromLatin1(",Segments=True"); - if (ui->groupsFaceColors->isChecked() && svp) { - // TODO: currently, we can only retrieve part feature - // color. The problem is that if the feature is linked, - // there are potentially many places where the color can - // get overridden. - // - // With topo naming feature merged, it will be possible to - // infer more accurate colors from just the shape names, - // with static function, - // - // PartGui::ViewProviderPartExt::getShapeColors(). - // - param += QString::fromLatin1(",GroupColors=Gui.getDocument('%1').getObject('%2').DiffuseColor") - .arg(QString::fromLatin1(sobj->getDocument()->getName()), - QString::fromLatin1(sobj->getNameInDocument())); - } - } - else if (method == Mefisto) { // Mefisto - double maxEdge = ui->spinMaximumEdgeLength->value().getValue(); - if (!ui->spinMaximumEdgeLength->isEnabled()) - maxEdge = 0; - param = QString::fromLatin1("Shape=__shape__,MaxLength=%1").arg(maxEdge); - } - else if (method == Netgen) { // Netgen - int fineness = ui->comboFineness->currentIndex(); - double growthRate = ui->doubleGrading->value(); - double nbSegPerEdge = ui->spinEdgeElements->value(); - double nbSegPerRadius = ui->spinCurvatureElements->value(); - bool secondOrder = ui->checkSecondOrder->isChecked(); - bool optimize = ui->checkOptimizeSurface->isChecked(); - bool allowquad = ui->checkQuadDominated->isChecked(); - if (fineness < 5) { - param = QString::fromLatin1("Shape=__shape__," - "Fineness=%1,SecondOrder=%2,Optimize=%3,AllowQuad=%4") - .arg(fineness) - .arg(secondOrder ? 1 : 0) - .arg(optimize ? 1 : 0) - .arg(allowquad ? 1 : 0); - } - else { - param = QString::fromLatin1("Shape=__shape__," - "GrowthRate=%1,SegPerEdge=%2,SegPerRadius=%3,SecondOrder=%4,Optimize=%5,AllowQuad=%6") - .arg(growthRate) - .arg(nbSegPerEdge) - .arg(nbSegPerRadius) - .arg(secondOrder ? 1 : 0) - .arg(optimize ? 1 : 0) - .arg(allowquad ? 1 : 0); - } - } + QString label = QString::fromUtf8(sobj->Label.getValue()); + + QString param = getMeshingParameters(method, sobj); QString cmd = QString::fromLatin1( "__doc__=FreeCAD.getDocument(\"%1\")\n" @@ -378,36 +292,159 @@ bool Tessellation::accept() Gui::Command::runCommand(Gui::Command::Doc, cmd.toUtf8()); - // if Standard mesher is used and face colors should be applied - if (method == Standard) { // Standard - if (ui->meshShapeColors->isChecked()) { - Gui::ViewProvider* vpm = Gui::Application::Instance->getViewProvider - (activeDoc->getActiveObject()); - MeshGui::ViewProviderMesh* vpmesh = dynamic_cast(vpm); - if (vpmesh && svp) { - std::vector diff_col = svp->DiffuseColor.getValues(); - if (ui->groupsFaceColors->isChecked()) { - // unique colors - std::set col_set; - for (auto it : diff_col) - col_set.insert(it.getPackedValue()); - diff_col.clear(); - for (auto it : col_set) - diff_col.push_back(App::Color(it)); - } - vpmesh->highlightSegments(diff_col); - } - } - } + setFaceColors(method, doc, sobj); } - activeDoc->commitTransaction(); + doc->commitTransaction(); } catch (const Base::Exception& e) { - activeDoc->abortTransaction(); + doc->abortTransaction(); Base::Console().Error(e.what()); } +} - return doClose; +void Tessellation::saveParameters(int method) +{ + if (method == Standard) { + ParameterGrp::handle handle = App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/Mod/Mesh/Meshing/Standard"); + double value = ui->spinSurfaceDeviation->value().getValue(); + handle->SetFloat("LinearDeflection", value); + double angle = ui->spinAngularDeviation->value().getValue(); + handle->SetFloat("AngularDeflection", angle); + bool relative = ui->relativeDeviation->isChecked(); + handle->SetBool("RelativeLinearDeflection", relative); + } +} + +void Tessellation::setFaceColors(int method, App::Document* doc, App::DocumentObject* obj) +{ + // if Standard mesher is used and face colors should be applied + if (method == Standard) { + if (ui->meshShapeColors->isChecked()) { + Gui::ViewProvider* vpm = Gui::Application::Instance->getViewProvider + (doc->getActiveObject()); + MeshGui::ViewProviderMesh* vpmesh = dynamic_cast(vpm); + + auto svp = Base::freecad_dynamic_cast( + Gui::Application::Instance->getViewProvider(obj)); + if (vpmesh && svp) { + std::vector diff_col = svp->DiffuseColor.getValues(); + if (ui->groupsFaceColors->isChecked()) { + diff_col = getUniqueColors(diff_col); + } + vpmesh->highlightSegments(diff_col); + } + } + } +} + +std::vector Tessellation::getUniqueColors(const std::vector& colors) const +{ + // unique colors + std::set col_set; + for (const auto& it : colors) + col_set.insert(it.getPackedValue()); + + std::vector unique; + for (const auto& it : col_set) + unique.push_back(App::Color(it)); + return unique; +} + +QString Tessellation::getMeshingParameters(int method, App::DocumentObject* obj) const +{ + QString param; + if (method == Standard) { + param = getStandardParameters(obj); + } + else if (method == Mefisto) { + param = getMefistoParameters(); + } + else if (method == Netgen) { + param = getNetgenParameters(); + } + + return param; +} + +QString Tessellation::getStandardParameters(App::DocumentObject* obj) const +{ + double devFace = ui->spinSurfaceDeviation->value().getValue(); + double devAngle = ui->spinAngularDeviation->value().getValue(); + devAngle = Base::toRadians(devAngle); + bool relative = ui->relativeDeviation->isChecked(); + + QString param; + param = QString::fromLatin1("Shape=__shape__, " + "LinearDeflection=%1, " + "AngularDeflection=%2, " + "Relative=%3") + .arg(devFace) + .arg(devAngle) + .arg(relative ? QString::fromLatin1("True") : QString::fromLatin1("False")); + if (ui->meshShapeColors->isChecked()) + param += QString::fromLatin1(",Segments=True"); + + auto svp = Base::freecad_dynamic_cast( + Gui::Application::Instance->getViewProvider(obj)); + if (ui->groupsFaceColors->isChecked() && svp) { + // TODO: currently, we can only retrieve part feature + // color. The problem is that if the feature is linked, + // there are potentially many places where the color can + // get overridden. + // + // With topo naming feature merged, it will be possible to + // infer more accurate colors from just the shape names, + // with static function, + // + // PartGui::ViewProviderPartExt::getShapeColors(). + // + param += QString::fromLatin1(",GroupColors=Gui.getDocument('%1').getObject('%2').DiffuseColor") + .arg(QString::fromLatin1(obj->getDocument()->getName()), + QString::fromLatin1(obj->getNameInDocument())); + } + + return param; +} + +QString Tessellation::getMefistoParameters() const +{ + double maxEdge = ui->spinMaximumEdgeLength->value().getValue(); + if (!ui->spinMaximumEdgeLength->isEnabled()) + maxEdge = 0; + return QString::fromLatin1("Shape=__shape__,MaxLength=%1").arg(maxEdge); +} + +QString Tessellation::getNetgenParameters() const +{ + QString param; + int fineness = ui->comboFineness->currentIndex(); + double growthRate = ui->doubleGrading->value(); + double nbSegPerEdge = ui->spinEdgeElements->value(); + double nbSegPerRadius = ui->spinCurvatureElements->value(); + bool secondOrder = ui->checkSecondOrder->isChecked(); + bool optimize = ui->checkOptimizeSurface->isChecked(); + bool allowquad = ui->checkQuadDominated->isChecked(); + if (fineness < 5) { + param = QString::fromLatin1("Shape=__shape__," + "Fineness=%1,SecondOrder=%2,Optimize=%3,AllowQuad=%4") + .arg(fineness) + .arg(secondOrder ? 1 : 0) + .arg(optimize ? 1 : 0) + .arg(allowquad ? 1 : 0); + } + else { + param = QString::fromLatin1("Shape=__shape__," + "GrowthRate=%1,SegPerEdge=%2,SegPerRadius=%3,SecondOrder=%4,Optimize=%5,AllowQuad=%6") + .arg(growthRate) + .arg(nbSegPerEdge) + .arg(nbSegPerRadius) + .arg(secondOrder ? 1 : 0) + .arg(optimize ? 1 : 0) + .arg(allowquad ? 1 : 0); + } + + return param; } // --------------------------------------- diff --git a/src/Mod/MeshPart/Gui/Tessellation.h b/src/Mod/MeshPart/Gui/Tessellation.h index 3d6033f16a..78ad45bc63 100644 --- a/src/Mod/MeshPart/Gui/Tessellation.h +++ b/src/Mod/MeshPart/Gui/Tessellation.h @@ -83,6 +83,14 @@ public: protected: void changeEvent(QEvent *e); + void process(int method, App::Document* doc, const std::list&); + void saveParameters(int method); + void setFaceColors(int method, App::Document* doc, App::DocumentObject* obj); + QString getMeshingParameters(int method, App::DocumentObject* obj) const; + QString getStandardParameters(App::DocumentObject* obj) const; + QString getMefistoParameters() const; + QString getNetgenParameters() const; + std::vector getUniqueColors(const std::vector& colors) const; private Q_SLOTS: void meshingMethod(int id);