diff --git a/src/Mod/Mesh/Gui/RemeshGmsh.cpp b/src/Mod/Mesh/Gui/RemeshGmsh.cpp
index de705d4af7..9651aac101 100644
--- a/src/Mod/Mesh/Gui/RemeshGmsh.cpp
+++ b/src/Mod/Mesh/Gui/RemeshGmsh.cpp
@@ -32,6 +32,7 @@
#include "RemeshGmsh.h"
#include "ui_RemeshGmsh.h"
+#include
#include
#include
#include
@@ -115,39 +116,6 @@ void GmshWidget::changeEvent(QEvent *e)
QWidget::changeEvent(e);
}
-#if 0 // this is for meshing a CAD shape see gmshtools.py write_geo
-// geo file for meshing with Gmsh meshing software created by FreeCAD
-
-// open brep geometry
-Merge "/tmp/fcfem_f1enjjfa/Part__Feature_Geometry.brep";
-
-// Characteristic Length
-// no boundary layer settings for this mesh
-// min, max Characteristic Length
-Mesh.CharacteristicLengthMax = 1e+22;
-Mesh.CharacteristicLengthMin = 0.0;
-
-// optimize the mesh
-Mesh.Optimize = 1;
-Mesh.OptimizeNetgen = 0;
-Mesh.HighOrderOptimize = 0; // for more HighOrderOptimize parameter check http://gmsh.info/doc/texinfo/gmsh.html
-
-// mesh order
-Mesh.ElementOrder = 2;
-Mesh.SecondOrderLinear = 1; // Second order nodes are created by linear interpolation instead by curvilinear
-
-// mesh algorithm, only a few algorithms are usable with 3D boundary layer generation
-// 2D mesh algorithm (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=BAMG, 8=DelQuad)
-Mesh.Algorithm = 2;
-// 3D mesh algorithm (1=Delaunay, 2=New Delaunay, 4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree)
-Mesh.Algorithm3D = 1;
-
-// meshing
-Geometry.Tolerance = 1e-06; // set geometrical tolerance (also used for merging nodes)
-Mesh 2;
-Coherence Mesh; // Remove duplicate vertices
-#endif
-
bool GmshWidget::writeProject(QString& inpFile, QString& outFile)
{
Q_UNUSED(inpFile)
@@ -183,6 +151,11 @@ double GmshWidget::getMinSize() const
void GmshWidget::accept()
{
+ if (d->gmsh.state() == QProcess::Running) {
+ Base::Console().Warning("Cannot start gmsh because it's already running\n");
+ return;
+ }
+
QString inpFile;
QString outFile;
if (writeProject(inpFile, outFile)) {
@@ -311,38 +284,6 @@ RemeshGmsh::~RemeshGmsh()
{
}
-#if 0 // this is for meshing a CAD shape see gmshtools.py write_geo
-// geo file for meshing with Gmsh meshing software created by FreeCAD
-
-// open brep geometry
-Merge "/tmp/fcfem_f1enjjfa/Part__Feature_Geometry.brep";
-
-// Characteristic Length
-// no boundary layer settings for this mesh
-// min, max Characteristic Length
-Mesh.CharacteristicLengthMax = 1e+22;
-Mesh.CharacteristicLengthMin = 0.0;
-
-// optimize the mesh
-Mesh.Optimize = 1;
-Mesh.OptimizeNetgen = 0;
-Mesh.HighOrderOptimize = 0; // for more HighOrderOptimize parameter check http://gmsh.info/doc/texinfo/gmsh.html
-
-// mesh order
-Mesh.ElementOrder = 2;
-Mesh.SecondOrderLinear = 1; // Second order nodes are created by linear interpolation instead by curvilinear
-
-// mesh algorithm, only a few algorithms are usable with 3D boundary layer generation
-// 2D mesh algorithm (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=BAMG, 8=DelQuad)
-Mesh.Algorithm = 2;
-// 3D mesh algorithm (1=Delaunay, 2=New Delaunay, 4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree)
-Mesh.Algorithm3D = 1;
-
-// meshing
-Geometry.Tolerance = 1e-06; // set geometrical tolerance (also used for merging nodes)
-Mesh 2;
-Coherence Mesh; // Remove duplicate vertices
-#endif
bool RemeshGmsh::writeProject(QString& inpFile, QString& outFile)
{
if (!d->mesh.expired()) {
diff --git a/src/Mod/MeshPart/Gui/Tessellation.cpp b/src/Mod/MeshPart/Gui/Tessellation.cpp
index 4e3fa0fc53..5722f964da 100644
--- a/src/Mod/MeshPart/Gui/Tessellation.cpp
+++ b/src/Mod/MeshPart/Gui/Tessellation.cpp
@@ -36,11 +36,14 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -53,6 +56,10 @@ Tessellation::Tessellation(QWidget* parent)
: QWidget(parent), ui(new Ui_Tessellation)
{
ui->setupUi(this);
+ gmsh = new Mesh2ShapeGmsh(this);
+ connect(gmsh, SIGNAL(processed()), this, SLOT(gmshProcessed()));
+
+ ui->stackedWidget->addTab(gmsh, tr("gmsh"));
ParameterGrp::handle handle = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Mod/Mesh/Meshing/Standard");
@@ -85,7 +92,8 @@ Tessellation::Tessellation(QWidget* parent)
Gui::Command::doCommand(Gui::Command::Doc, "import MeshPart");
}
catch (...) {
- ui->stackedWidget->setDisabled(true);
+ ui->stackedWidget->setTabEnabled(Mefisto, false);
+ ui->stackedWidget->setTabEnabled(Netgen, false);
}
}
@@ -154,6 +162,13 @@ void Tessellation::on_checkQuadDominated_toggled(bool on)
ui->checkSecondOrder->setChecked(false);
}
+void Tessellation::gmshProcessed()
+{
+ bool doClose = !ui->checkBoxDontQuit->isChecked();
+ if (doClose)
+ Gui::Control().reject();
+}
+
void Tessellation::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
@@ -233,12 +248,24 @@ bool Tessellation::accept()
return false;
}
+ bool doClose = !ui->checkBoxDontQuit->isChecked();
+ int method = ui->stackedWidget->currentIndex();
+
+ // 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);
+ return false;
+ }
+
try {
QString objname, label, subname;
Gui::WaitCursor wc;
- int method = ui->stackedWidget->currentIndex();
-
// Save parameters
if (method == Standard) {
ParameterGrp::handle handle = App::GetApplication().GetParameterGroupByPath
@@ -380,6 +407,137 @@ bool Tessellation::accept()
Base::Console().Error(e.what());
}
+ return doClose;
+}
+
+// ---------------------------------------
+
+class Mesh2ShapeGmsh::Private {
+public:
+ std::string label;
+ std::list shapes;
+ App::DocumentT doc;
+ std::string cadFile;
+ std::string stlFile;
+ std::string geoFile;
+};
+
+Mesh2ShapeGmsh::Mesh2ShapeGmsh(QWidget* parent, Qt::WindowFlags fl)
+ : GmshWidget(parent, fl)
+ , d(new Private())
+{
+ d->cadFile = App::Application::getTempFileName() + "mesh.brep";
+ d->stlFile = App::Application::getTempFileName() + "mesh.stl";
+ d->geoFile = App::Application::getTempFileName() + "mesh.geo";
+}
+
+Mesh2ShapeGmsh::~Mesh2ShapeGmsh()
+{
+}
+
+void Mesh2ShapeGmsh::process(App::Document* doc, const std::list& objs)
+{
+ d->doc = doc;
+ d->shapes = objs;
+
+ doc->openTransaction("Meshing");
+ accept();
+}
+
+bool Mesh2ShapeGmsh::writeProject(QString& inpFile, QString& outFile)
+{
+ if (!d->shapes.empty()) {
+ App::SubObjectT sub = d->shapes.front();
+ d->shapes.pop_front();
+
+ App::DocumentObject* part = sub.getObject();
+ if (part) {
+ Part::TopoShape shape = Part::Feature::getTopoShape(part, sub.getSubName().c_str());
+ shape.exportBrep(d->cadFile.c_str());
+ d->label = part->Label.getStrValue() + " (Meshed)";
+
+ // Parameters
+ int algorithm = meshingAlgorithm();
+ double maxSize = getMaxSize();
+ if (maxSize == 0.0)
+ maxSize = 1.0e22;
+ double minSize = getMinSize();
+
+ // gmsh geo file
+ Base::FileInfo geo(d->geoFile);
+ Base::ofstream geoOut(geo, std::ios::out);
+ geoOut << "// geo file for meshing with Gmsh meshing software created by FreeCAD\n"
+ << "// open brep geometry\n"
+ << "Merge \"" << d->cadFile << "\";\n\n"
+ << "// Characteristic Length\n"
+ << "// no boundary layer settings for this mesh\n"
+ << "// min, max Characteristic Length\n"
+ << "Mesh.CharacteristicLengthMax = " << maxSize << ";\n"
+ << "Mesh.CharacteristicLengthMin = " << minSize << ";\n\n"
+ << "// optimize the mesh\n"
+ << "Mesh.Optimize = 1;\n"
+ << "Mesh.OptimizeNetgen = 0;\n"
+ << "// for more HighOrderOptimize parameter check http://gmsh.info/doc/texinfo/gmsh.html\n"
+ << "Mesh.HighOrderOptimize = 0;\n\n"
+ << "// mesh order\n"
+ << "Mesh.ElementOrder = 2;\n"
+ << "// Second order nodes are created by linear interpolation instead by curvilinear\n"
+ << "Mesh.SecondOrderLinear = 1;\n\n"
+ << "// mesh algorithm, only a few algorithms are usable with 3D boundary layer generation\n"
+ << "// 2D mesh algorithm (1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=BAMG, 8=DelQuad)\n"
+ << "Mesh.Algorithm = " << algorithm << ";\n"
+ << "// 3D mesh algorithm (1=Delaunay, 2=New Delaunay, 4=Frontal, 5=Frontal Delaunay, 6=Frontal Hex, 7=MMG3D, 9=R-tree)\n"
+ << "Mesh.Algorithm3D = 1;\n\n"
+ << "// meshing\n"
+ << "// set geometrical tolerance (also used for merging nodes)\n"
+ << "Geometry.Tolerance = 1e-06;\n"
+ << "Mesh 2;\n"
+ << "Coherence Mesh; // Remove duplicate vertices\n";
+ geoOut.close();
+
+ inpFile = QString::fromUtf8(d->geoFile.c_str());
+ outFile = QString::fromUtf8(d->stlFile.c_str());
+
+ return true;
+ }
+ }
+ else {
+ App::Document* doc = d->doc.getDocument();
+ if (doc)
+ doc->commitTransaction();
+
+ Q_EMIT processed();
+ }
+
+ return false;
+}
+
+bool Mesh2ShapeGmsh::loadOutput()
+{
+ App::Document* doc = d->doc.getDocument();
+ if (!doc)
+ return false;
+
+ // Now read-in the mesh
+ Base::FileInfo stl(d->stlFile);
+ Base::FileInfo geo(d->geoFile);
+
+ Mesh::MeshObject kernel;
+ MeshCore::MeshInput input(kernel.getKernel());
+ Base::ifstream stlIn(stl, std::ios::in | std::ios::binary);
+ input.LoadBinarySTL(stlIn);
+ stlIn.close();
+ kernel.harmonizeNormals();
+
+ Mesh::Feature* fea = static_cast(doc->addObject("Mesh::Feature", "Mesh"));
+ fea->Label.setValue(d->label);
+ fea->Mesh.setValue(kernel.getKernel());
+ stl.deleteFile();
+ geo.deleteFile();
+
+ // process next object
+ accept();
+
return true;
}
diff --git a/src/Mod/MeshPart/Gui/Tessellation.h b/src/Mod/MeshPart/Gui/Tessellation.h
index 17c07b59d5..ea55ea2fb7 100644
--- a/src/Mod/MeshPart/Gui/Tessellation.h
+++ b/src/Mod/MeshPart/Gui/Tessellation.h
@@ -28,10 +28,42 @@
#include
#include
#include
+#include
#include
+#include
+namespace App {
+class Document;
+class SubObjectT;
+}
namespace MeshPartGui {
+/**
+ * Non-modal dialog to mesh a shape.
+ * @author Werner Mayer
+ */
+class MeshGuiExport Mesh2ShapeGmsh : public MeshGui::GmshWidget
+{
+ Q_OBJECT
+
+public:
+ Mesh2ShapeGmsh(QWidget* parent = 0, Qt::WindowFlags fl = 0);
+ ~Mesh2ShapeGmsh();
+
+ void process(App::Document* doc, const std::list&);
+
+Q_SIGNALS:
+ void processed();
+
+protected:
+ virtual bool writeProject(QString& inpFile, QString& outFile);
+ virtual bool loadOutput();
+
+private:
+ class Private;
+ std::unique_ptr d;
+};
+
class Ui_Tessellation;
class Tessellation : public QWidget
{
@@ -40,7 +72,8 @@ class Tessellation : public QWidget
enum {
Standard,
Mefisto,
- Netgen
+ Netgen,
+ Gmsh
};
public:
@@ -57,9 +90,11 @@ private Q_SLOTS:
void on_comboFineness_currentIndexChanged(int);
void on_checkSecondOrder_toggled(bool);
void on_checkQuadDominated_toggled(bool);
+ void gmshProcessed();
private:
QString document;
+ QPointer gmsh;
std::unique_ptr ui;
};
diff --git a/src/Mod/MeshPart/Gui/Tessellation.ui b/src/Mod/MeshPart/Gui/Tessellation.ui
index 4971bc48e8..84a781bc0b 100644
--- a/src/Mod/MeshPart/Gui/Tessellation.ui
+++ b/src/Mod/MeshPart/Gui/Tessellation.ui
@@ -416,6 +416,13 @@ A value in the range of 0.2-10.
+ -
+
+
+ Leave panel open
+
+
+