MeshPart: apply clang format

This commit is contained in:
wmayer
2023-09-02 01:36:28 +02:00
committed by wwmayer
parent c2bda2f756
commit 6fb2bcafe8
14 changed files with 633 additions and 508 deletions

View File

@@ -43,13 +43,15 @@ void loadMeshPartResource()
Gui::Translator::instance()->refresh();
}
namespace MeshPartGui {
class Module : public Py::ExtensionModule<Module>
namespace MeshPartGui
{
class Module: public Py::ExtensionModule<Module>
{
public:
Module() : Py::ExtensionModule<Module>("MeshPartGui")
Module()
: Py::ExtensionModule<Module>("MeshPartGui")
{
initialize("This module is the MeshPartGui module."); // register with Python
initialize("This module is the MeshPartGui module.");// register with Python
}
private:
@@ -60,7 +62,7 @@ PyObject* initModule()
return Base::Interpreter().addModule(new Module);
}
} // namespace MeshPartGui
}// namespace MeshPartGui
/* Python entry */
@@ -74,12 +76,14 @@ PyMOD_INIT_FUNC(MeshPartGui)
PyObject* mod = MeshPartGui::initModule();
Base::Console().Log("Loading GUI of MeshPart module... done\n");
// clang-format off
// instantiating the commands
CreateMeshPartCommands();
MeshPartGui::Workbench ::init();
MeshPartGui::ViewProviderCurveOnMesh ::init();
// clang-format on
// add resources and reloads the translators
// add resources and reloads the translators
loadMeshPartResource();
PyMOD_Return(mod);

View File

@@ -22,9 +22,9 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QApplication>
# include <QMessageBox>
# include <QPushButton>
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#endif
#include <App/Application.h>
@@ -52,14 +52,14 @@ using namespace std;
DEF_STD_CMD_A(CmdMeshPartMesher)
CmdMeshPartMesher::CmdMeshPartMesher()
: Command("MeshPart_Mesher")
: Command("MeshPart_Mesher")
{
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Create mesh from shape...");
sToolTipText = QT_TR_NOOP("Tessellate shape");
sWhatsThis = "MeshPart_Mesher";
sStatusTip = sToolTipText;
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Create mesh from shape...");
sToolTipText = QT_TR_NOOP("Tessellate shape");
sWhatsThis = "MeshPart_Mesher";
sStatusTip = sToolTipText;
}
void CmdMeshPartMesher::activated(int)
@@ -77,13 +77,13 @@ bool CmdMeshPartMesher::isActive()
DEF_STD_CMD_A(CmdMeshPartTrimByPlane)
CmdMeshPartTrimByPlane::CmdMeshPartTrimByPlane()
: Command("MeshPart_TrimByPlane")
: Command("MeshPart_TrimByPlane")
{
sAppModule = "Mesh";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Trim mesh with a plane");
sToolTipText = QT_TR_NOOP("Trims a mesh with a plane");
sStatusTip = QT_TR_NOOP("Trims a mesh with a plane");
sAppModule = "Mesh";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Trim mesh with a plane");
sToolTipText = QT_TR_NOOP("Trims a mesh with a plane");
sStatusTip = QT_TR_NOOP("Trims a mesh with a plane");
}
void CmdMeshPartTrimByPlane::activated(int)
@@ -92,18 +92,22 @@ void CmdMeshPartTrimByPlane::activated(int)
std::vector<App::DocumentObject*> plane = getSelection().getObjectsOfType(partType);
if (plane.empty()) {
QMessageBox::warning(Gui::getMainWindow(),
qApp->translate("MeshPart_TrimByPlane", "Select plane"),
qApp->translate("MeshPart_TrimByPlane", "Please select a plane at which you trim the mesh."));
qApp->translate("MeshPart_TrimByPlane", "Select plane"),
qApp->translate("MeshPart_TrimByPlane",
"Please select a plane at which you trim the mesh."));
return;
}
QMessageBox msgBox(Gui::getMainWindow());
msgBox.setIcon(QMessageBox::Question);
msgBox.setWindowTitle(qApp->translate("MeshPart_TrimByPlane","Trim by plane"));
msgBox.setText(qApp->translate("MeshPart_TrimByPlane","Select the side you want to keep."));
QPushButton* inner = msgBox.addButton(qApp->translate("MeshPart_TrimByPlane","Below"), QMessageBox::ActionRole);
QPushButton* outer = msgBox.addButton(qApp->translate("MeshPart_TrimByPlane","Above"), QMessageBox::ActionRole);
QPushButton* split = msgBox.addButton(qApp->translate("MeshPart_TrimByPlane","Split"), QMessageBox::ActionRole);
msgBox.setWindowTitle(qApp->translate("MeshPart_TrimByPlane", "Trim by plane"));
msgBox.setText(qApp->translate("MeshPart_TrimByPlane", "Select the side you want to keep."));
QPushButton* inner =
msgBox.addButton(qApp->translate("MeshPart_TrimByPlane", "Below"), QMessageBox::ActionRole);
QPushButton* outer =
msgBox.addButton(qApp->translate("MeshPart_TrimByPlane", "Above"), QMessageBox::ActionRole);
QPushButton* split =
msgBox.addButton(qApp->translate("MeshPart_TrimByPlane", "Split"), QMessageBox::ActionRole);
msgBox.addButton(QMessageBox::Cancel);
msgBox.setDefaultButton(inner);
msgBox.exec();
@@ -124,12 +128,14 @@ void CmdMeshPartTrimByPlane::activated(int)
return;
}
Base::Placement plnPlacement = static_cast<App::GeoFeature*>(plane.front())->Placement.getValue();
Base::Placement plnPlacement =
static_cast<App::GeoFeature*>(plane.front())->Placement.getValue();
openCommand(QT_TRANSLATE_NOOP("Command", "Trim with plane"));
std::vector<App::DocumentObject*> docObj = Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId());
std::vector<App::DocumentObject*> docObj =
Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId());
for (auto it : docObj) {
Base::Vector3d normal(0,0,1);
Base::Vector3d normal(0, 0, 1);
plnPlacement.getRotation().multVec(normal, normal);
Base::Vector3d base = plnPlacement.getPosition();
@@ -167,8 +173,9 @@ void CmdMeshPartTrimByPlane::activated(int)
bool CmdMeshPartTrimByPlane::isActive()
{
// Check for the selected mesh feature (all Mesh types)
if (getSelection().countObjectsOfType(Mesh::Feature::getClassTypeId()) != 1)
if (getSelection().countObjectsOfType(Mesh::Feature::getClassTypeId()) != 1) {
return false;
}
return true;
}
@@ -179,14 +186,14 @@ bool CmdMeshPartTrimByPlane::isActive()
DEF_STD_CMD_A(CmdMeshPartSection)
CmdMeshPartSection::CmdMeshPartSection()
: Command("MeshPart_SectionByPlane")
: Command("MeshPart_SectionByPlane")
{
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Create section from mesh and plane");
sToolTipText = QT_TR_NOOP("Section");
sWhatsThis = "MeshPart_Section";
sStatusTip = sToolTipText;
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Create section from mesh and plane");
sToolTipText = QT_TR_NOOP("Section");
sWhatsThis = "MeshPart_Section";
sStatusTip = sToolTipText;
}
void CmdMeshPartSection::activated(int)
@@ -194,19 +201,22 @@ void CmdMeshPartSection::activated(int)
Base::Type partType = Base::Type::fromName("Part::Plane");
std::vector<App::DocumentObject*> plane = getSelection().getObjectsOfType(partType);
if (plane.empty()) {
QMessageBox::warning(Gui::getMainWindow(),
QMessageBox::warning(
Gui::getMainWindow(),
qApp->translate("MeshPart_Section", "Select plane"),
qApp->translate("MeshPart_Section", "Please select a plane at which you section the mesh."));
qApp->translate("MeshPart_Section",
"Please select a plane at which you section the mesh."));
return;
}
Base::Placement plm = static_cast<App::GeoFeature*>(plane.front())->Placement.getValue();
Base::Vector3d normal(0,0,1);
Base::Vector3d normal(0, 0, 1);
plm.getRotation().multVec(normal, normal);
Base::Vector3d base = plm.getPosition();
openCommand(QT_TRANSLATE_NOOP("Command", "Section with plane"));
std::vector<App::DocumentObject*> docObj = Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId());
std::vector<App::DocumentObject*> docObj =
Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId());
Mesh::MeshObject::TPlane tplane;
tplane.first = Base::convertTo<Base::Vector3f>(base);
tplane.second = Base::convertTo<Base::Vector3f>(normal);
@@ -251,8 +261,9 @@ void CmdMeshPartSection::activated(int)
bool CmdMeshPartSection::isActive()
{
// Check for the selected mesh feature (all Mesh types)
if (getSelection().countObjectsOfType(Mesh::Feature::getClassTypeId()) != 1)
if (getSelection().countObjectsOfType(Mesh::Feature::getClassTypeId()) != 1) {
return false;
}
return true;
}
@@ -263,15 +274,15 @@ bool CmdMeshPartSection::isActive()
DEF_STD_CMD_A(CmdMeshPartCrossSections)
CmdMeshPartCrossSections::CmdMeshPartCrossSections()
:Command("MeshPart_CrossSections")
: Command("MeshPart_CrossSections")
{
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("MeshPart");
sMenuText = QT_TR_NOOP("Cross-sections...");
sToolTipText = QT_TR_NOOP("Cross-sections");
sWhatsThis = "MeshPart_CrossSections";
sStatusTip = sToolTipText;
//sPixmap = "MeshPart_CrossSections";
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("MeshPart");
sMenuText = QT_TR_NOOP("Cross-sections...");
sToolTipText = QT_TR_NOOP("Cross-sections");
sWhatsThis = "MeshPart_CrossSections";
sStatusTip = sToolTipText;
// sPixmap = "MeshPart_CrossSections";
}
void CmdMeshPartCrossSections::activated(int iMsg)
@@ -279,8 +290,8 @@ void CmdMeshPartCrossSections::activated(int iMsg)
Q_UNUSED(iMsg);
Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
if (!dlg) {
std::vector<App::DocumentObject*> obj = Gui::Selection().getObjectsOfType
(Mesh::Feature::getClassTypeId());
std::vector<App::DocumentObject*> obj =
Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId());
Base::BoundBox3d bbox;
for (auto it : obj) {
bbox.Add(static_cast<Mesh::Feature*>(it)->Mesh.getBoundingBox());
@@ -292,23 +303,23 @@ void CmdMeshPartCrossSections::activated(int iMsg)
bool CmdMeshPartCrossSections::isActive()
{
return (Gui::Selection().countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0 &&
!Gui::Control().activeDialog());
return (Gui::Selection().countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0
&& !Gui::Control().activeDialog());
}
DEF_STD_CMD_A(CmdMeshPartCurveOnMesh)
CmdMeshPartCurveOnMesh::CmdMeshPartCurveOnMesh()
: Command("MeshPart_CurveOnMesh")
: Command("MeshPart_CurveOnMesh")
{
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Curve on mesh...");
sToolTipText = QT_TR_NOOP("Creates an approximated curve on top of a mesh.\n"
"This command only works with a 'mesh' object.");
sWhatsThis = "MeshPart_CurveOnMesh";
sStatusTip = sToolTipText;
sPixmap = "MeshPart_CurveOnMesh";
sAppModule = "MeshPart";
sGroup = QT_TR_NOOP("Mesh");
sMenuText = QT_TR_NOOP("Curve on mesh...");
sToolTipText = QT_TR_NOOP("Creates an approximated curve on top of a mesh.\n"
"This command only works with a 'mesh' object.");
sWhatsThis = "MeshPart_CurveOnMesh";
sStatusTip = sToolTipText;
sPixmap = "MeshPart_CurveOnMesh";
}
void CmdMeshPartCurveOnMesh::activated(int)
@@ -319,18 +330,21 @@ void CmdMeshPartCurveOnMesh::activated(int)
return;
}
Gui::Control().showDialog(new MeshPartGui::TaskCurveOnMesh(static_cast<Gui::View3DInventor*>(mdis.front())));
Gui::Control().showDialog(
new MeshPartGui::TaskCurveOnMesh(static_cast<Gui::View3DInventor*>(mdis.front())));
}
bool CmdMeshPartCurveOnMesh::isActive()
{
if (Gui::Control().activeDialog())
if (Gui::Control().activeDialog()) {
return false;
}
// Check for the selected mesh feature (all Mesh types)
App::Document* doc = App::GetApplication().getActiveDocument();
if (doc && doc->countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0)
if (doc && doc->countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0) {
return true;
}
return false;
}
@@ -338,7 +352,7 @@ bool CmdMeshPartCurveOnMesh::isActive()
void CreateMeshPartCommands()
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.addCommand(new CmdMeshPartMesher());
rcCmdMgr.addCommand(new CmdMeshPartTrimByPlane());
rcCmdMgr.addCommand(new CmdMeshPartSection());

View File

@@ -22,24 +22,24 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cfloat>
# include <sstream>
#include <cfloat>
#include <sstream>
# include <BRep_Builder.hxx>
# include <BRepBuilderAPI_MakePolygon.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Compound.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRep_Builder.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
# include <QFuture>
# include <QKeyEvent>
# include <QMessageBox>
# include <QtConcurrentMap>
#include <QFuture>
#include <QKeyEvent>
#include <QMessageBox>
#include <QtConcurrentMap>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoCoordinate3.h>
# include <Inventor/nodes/SoDrawStyle.h>
# include <Inventor/nodes/SoLineSet.h>
# include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoBaseColor.h>
#include <Inventor/nodes/SoCoordinate3.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoLineSet.h>
#include <Inventor/nodes/SoSeparator.h>
#endif
#include <App/Document.h>
@@ -47,14 +47,14 @@
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
#include <Gui/ViewProvider.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Gui/ViewProvider.h>
#include <Mod/Mesh/App/Core/Algorithm.h>
#include <Mod/Mesh/App/Core/Grid.h>
#include <Mod/Mesh/App/MeshFeature.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/Tools.h>
#include <Mod/Mesh/App/Core/Algorithm.h>
#include <Mod/Mesh/App/Core/Grid.h>
#include "CrossSections.h"
#include "ui_CrossSections.h"
@@ -63,8 +63,9 @@
using namespace MeshPartGui;
namespace sp = std::placeholders;
namespace MeshPartGui {
class ViewProviderCrossSections : public Gui::ViewProvider
namespace MeshPartGui
{
class ViewProviderCrossSections: public Gui::ViewProvider
{
public:
ViewProviderCrossSections()
@@ -88,8 +89,7 @@ public:
planes->unref();
}
void updateData(const App::Property*) override
{
}
{}
const char* getDefaultDisplayMode() const override
{
return "";
@@ -102,15 +102,15 @@ public:
{
coords->point.setNum(v.size());
SbVec3f* p = coords->point.startEditing();
for (unsigned int i=0; i<v.size(); i++) {
for (unsigned int i = 0; i < v.size(); i++) {
const Base::Vector3f& pt = v[i];
p[i].setValue(pt.x,pt.y,pt.z);
p[i].setValue(pt.x, pt.y, pt.z);
}
coords->point.finishEditing();
unsigned int count = v.size()/5;
unsigned int count = v.size() / 5;
planes->numVertices.setNum(count);
int32_t* l = planes->numVertices.startEditing();
for (unsigned int i=0; i<count; i++) {
for (unsigned int i = 0; i < count; i++) {
l[i] = 5;
}
planes->numVertices.finishEditing();
@@ -121,12 +121,16 @@ private:
SoLineSet* planes;
};
class MeshCrossSection {
class MeshCrossSection
{
public:
MeshCrossSection(const MeshCore::MeshKernel& mesh,
const MeshCore::MeshFacetGrid& grid,
double x, double y, double z,
bool connectEdges, double eps)
double x,
double y,
double z,
bool connectEdges,
double eps)
: mesh(mesh)
, grid(grid)
, x(x)
@@ -134,25 +138,25 @@ public:
, z(z)
, connectEdges(connectEdges)
, epsilon(eps)
{
}
{}
std::list<TopoDS_Wire> section(double d)
{
Mesh::MeshObject::TPolylines polylines;
MeshCore::MeshAlgorithm algo(mesh);
Base::Vector3f p(x*d, y*d, z*d);
Base::Vector3f p(x * d, y * d, z * d);
Base::Vector3f n(x, y, z);
algo.CutWithPlane(p, n, grid, polylines, epsilon, connectEdges);
std::list<TopoDS_Wire> wires;
for (const auto & polyline : polylines) {
for (const auto& polyline : polylines) {
BRepBuilderAPI_MakePolygon mkPoly;
for (auto jt : polyline) {
mkPoly.Add(Base::convertTo<gp_Pnt>(jt));
}
if (mkPoly.IsDone())
if (mkPoly.IsDone()) {
wires.push_back(mkPoly.Wire());
}
}
return wires;
@@ -161,14 +165,15 @@ public:
private:
const MeshCore::MeshKernel& mesh;
const MeshCore::MeshFacetGrid& grid;
double x,y,z;
double x, y, z;
bool connectEdges;
double epsilon;
};
}
}// namespace MeshPartGui
CrossSections::CrossSections(const Base::BoundBox3d& bb, QWidget* parent, Qt::WindowFlags fl)
: QDialog(parent, fl), bbox(bb)
: QDialog(parent, fl)
, bbox(bb)
{
ui = new Ui_CrossSections();
ui->setupUi(this);
@@ -207,13 +212,14 @@ CrossSections::~CrossSections()
void CrossSections::setupConnections()
{
// clang-format off
connect(ui->xyPlane, &QRadioButton::clicked,
this, &CrossSections::xyPlaneClicked);
connect(ui->xzPlane, &QRadioButton::clicked,
this, &CrossSections::xzPlaneClicked);
connect(ui->yzPlane, &QRadioButton::clicked,
this, &CrossSections::yzPlaneClicked);
connect(ui->position, qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
connect(ui->position,qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this, &CrossSections::positionValueChanged);
connect(ui->distance, qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this, &CrossSections::distanceValueChanged);
@@ -223,20 +229,23 @@ void CrossSections::setupConnections()
this, &CrossSections::checkBothSidesToggled);
connect(ui->sectionsBox, &QGroupBox::toggled,
this, &CrossSections::sectionsBoxToggled);
// clang-format on
}
CrossSections::Plane CrossSections::plane() const
{
if (ui->xyPlane->isChecked())
if (ui->xyPlane->isChecked()) {
return CrossSections::XY;
else if (ui->xzPlane->isChecked())
}
else if (ui->xzPlane->isChecked()) {
return CrossSections::XZ;
else
}
else {
return CrossSections::YZ;
}
}
void CrossSections::changeEvent(QEvent *e)
void CrossSections::changeEvent(QEvent* e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
@@ -261,15 +270,17 @@ void CrossSections::accept()
void CrossSections::apply()
{
std::vector<App::DocumentObject*> obj = Gui::Selection().
getObjectsOfType(Mesh::Feature::getClassTypeId());
std::vector<App::DocumentObject*> obj =
Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId());
std::vector<double> d;
if (ui->sectionsBox->isChecked())
if (ui->sectionsBox->isChecked()) {
d = getPlanes();
else
}
else {
d.push_back(ui->position->value().getValue());
double a=0,b=0,c=0;
}
double a = 0, b = 0, c = 0;
switch (plane()) {
case CrossSections::XY:
c = 1.0;
@@ -285,7 +296,7 @@ void CrossSections::apply()
bool connectEdges = ui->checkBoxConnect->isChecked();
double eps = ui->spinEpsilon->value();
#if 1 // multi-threaded sections
#if 1// multi-threaded sections
for (auto it : obj) {
const Mesh::MeshObject& mesh = static_cast<Mesh::Feature*>(it)->Mesh.getValue();
@@ -294,29 +305,30 @@ void CrossSections::apply()
MeshCore::MeshFacetGrid grid(kernel);
//NOLINTBEGIN
// NOLINTBEGIN
MeshCrossSection cs(kernel, grid, a, b, c, connectEdges, eps);
QFuture< std::list<TopoDS_Wire> > future = QtConcurrent::mapped
(d, std::bind(&MeshCrossSection::section, &cs, sp::_1));
QFuture<std::list<TopoDS_Wire>> future =
QtConcurrent::mapped(d, std::bind(&MeshCrossSection::section, &cs, sp::_1));
future.waitForFinished();
//NOLINTEND
// NOLINTEND
TopoDS_Compound comp;
BRep_Builder builder;
builder.MakeCompound(comp);
for (const auto & w : future) {
for (const auto & wt : w) {
if (!wt.IsNull())
for (const auto& w : future) {
for (const auto& wt : w) {
if (!wt.IsNull()) {
builder.Add(comp, wt);
}
}
}
App::Document* doc = it->getDocument();
std::string s = it->getNameInDocument();
s += "_cs";
Part::Feature* section = static_cast<Part::Feature*>
(doc->addObject("Part::Feature",s.c_str()));
Part::Feature* section =
static_cast<Part::Feature*>(doc->addObject("Part::Feature", s.c_str()));
section->Shape.setValue(comp);
section->purgeTouched();
}
@@ -330,8 +342,8 @@ void CrossSections::apply()
for (std::vector<double>::iterator jt = d.begin(); jt != d.end(); ++jt) {
double d = *jt;
str << "("
<< "App.Vector(" << a*d << ", " << b*d << ", " << c*d << "), "
<< "App.Vector(" << a << ", " << b << ", " << c << ")"
<< "App.Vector(" << a * d << ", " << b * d << ", " << c * d << "), "
<< "App.Vector(" << a << ", " << b << ", " << c << ")"
<< "), ";
}
str << "]";
@@ -341,26 +353,31 @@ void CrossSections::apply()
App::Document* doc = (*it)->getDocument();
std::string s = (*it)->getNameInDocument();
s += "_cs";
Gui::Command::runCommand(Gui::Command::App, QString::fromLatin1(
"points=FreeCAD.getDocument(\"%1\").%2.Mesh.crossSections(%3, %4, %5)\n"
"wires=[]\n"
"for i in points:\n"
" wires.extend([Part.makePolygon(j) for j in i])\n")
.arg(QLatin1String(doc->getName()))
.arg(QLatin1String((*it)->getNameInDocument()))
.arg(planes)
.arg(eps)
.arg(connectEdges ? QLatin1String("True") : QLatin1String("False"))
.toLatin1());
Gui::Command::runCommand(
Gui::Command::App,
QString::fromLatin1(
"points=FreeCAD.getDocument(\"%1\").%2.Mesh.crossSections(%3, %4, %5)\n"
"wires=[]\n"
"for i in points:\n"
" wires.extend([Part.makePolygon(j) for j in i])\n")
.arg(QLatin1String(doc->getName()))
.arg(QLatin1String((*it)->getNameInDocument()))
.arg(planes)
.arg(eps)
.arg(connectEdges ? QLatin1String("True") : QLatin1String("False"))
.toLatin1());
Gui::Command::runCommand(Gui::Command::App, QString::fromLatin1(
"comp=Part.Compound(wires)\n"
"slice=FreeCAD.getDocument(\"%1\").addObject(\"Part::Feature\",\"%2\")\n"
"slice.Shape=comp\n"
"slice.purgeTouched()\n"
"del slice,comp,wires,points")
.arg(QLatin1String(doc->getName()))
.arg(QLatin1String(s.c_str())).toLatin1());
Gui::Command::runCommand(
Gui::Command::App,
QString::fromLatin1(
"comp=Part.Compound(wires)\n"
"slice=FreeCAD.getDocument(\"%1\").addObject(\"Part::Feature\",\"%2\")\n"
"slice.Shape=comp\n"
"slice.purgeTouched()\n"
"del slice,comp,wires,points")
.arg(QLatin1String(doc->getName()))
.arg(QLatin1String(s.c_str()))
.toLatin1());
}
}
catch (const Base::Exception& e) {
@@ -378,8 +395,9 @@ void CrossSections::xyPlaneClicked()
}
else {
double dist = bbox.LengthZ() / ui->countSections->value();
if (!ui->checkBothSides->isChecked())
if (!ui->checkBothSides->isChecked()) {
dist *= 0.5f;
}
ui->distance->setValue(dist);
calcPlanes(CrossSections::XY);
}
@@ -394,8 +412,9 @@ void CrossSections::xzPlaneClicked()
}
else {
double dist = bbox.LengthY() / ui->countSections->value();
if (!ui->checkBothSides->isChecked())
if (!ui->checkBothSides->isChecked()) {
dist *= 0.5f;
}
ui->distance->setValue(dist);
calcPlanes(CrossSections::XZ);
}
@@ -410,8 +429,9 @@ void CrossSections::yzPlaneClicked()
}
else {
double dist = bbox.LengthX() / ui->countSections->value();
if (!ui->checkBothSides->isChecked())
if (!ui->checkBothSides->isChecked()) {
dist *= 0.5f;
}
ui->distance->setValue(dist);
calcPlanes(CrossSections::YZ);
}
@@ -476,8 +496,9 @@ void CrossSections::countSectionsValueChanged(int v)
dist = bbox.LengthX() / v;
break;
}
if (!ui->checkBothSides->isChecked())
if (!ui->checkBothSides->isChecked()) {
dist *= 0.5f;
}
ui->distance->setValue(dist);
calcPlanes(type);
}
@@ -553,14 +574,14 @@ std::vector<double> CrossSections::getPlanes() const
std::vector<double> d;
if (both) {
double start = pos-0.5f*(count-1)*stp;
for (int i=0; i<count; i++) {
d.push_back(start+i*stp);
double start = pos - 0.5f * (count - 1) * stp;
for (int i = 0; i < count; i++) {
d.push_back(start + i * stp);
}
}
else {
for (int i=0; i<count; i++) {
d.push_back(pos+i*stp);
for (int i = 0; i < count; i++) {
d.push_back(pos + i * stp);
}
}
return d;
@@ -573,22 +594,22 @@ void CrossSections::makePlanes(Plane type, const std::vector<double>& d, double
Base::Vector3f v[4];
switch (type) {
case XY:
v[0].Set(bound[0],bound[2],it);
v[1].Set(bound[1],bound[2],it);
v[2].Set(bound[1],bound[3],it);
v[3].Set(bound[0],bound[3],it);
v[0].Set(bound[0], bound[2], it);
v[1].Set(bound[1], bound[2], it);
v[2].Set(bound[1], bound[3], it);
v[3].Set(bound[0], bound[3], it);
break;
case XZ:
v[0].Set(bound[0],it,bound[2]);
v[1].Set(bound[1],it,bound[2]);
v[2].Set(bound[1],it,bound[3]);
v[3].Set(bound[0],it,bound[3]);
v[0].Set(bound[0], it, bound[2]);
v[1].Set(bound[1], it, bound[2]);
v[2].Set(bound[1], it, bound[3]);
v[3].Set(bound[0], it, bound[3]);
break;
case YZ:
v[0].Set(it,bound[0],bound[2]);
v[1].Set(it,bound[1],bound[2]);
v[2].Set(it,bound[1],bound[3]);
v[3].Set(it,bound[0],bound[3]);
v[0].Set(it, bound[0], bound[2]);
v[1].Set(it, bound[1], bound[2]);
v[2].Set(it, bound[1], bound[3]);
v[3].Set(it, bound[0], bound[3]);
break;
}
@@ -606,9 +627,10 @@ void CrossSections::makePlanes(Plane type, const std::vector<double>& d, double
TaskCrossSections::TaskCrossSections(const Base::BoundBox3d& bb)
{
widget = new CrossSections(bb);
taskbox = new Gui::TaskView::TaskBox(
Gui::BitmapFactory().pixmap("Mesh_CrossSections"),
widget->windowTitle(), true, nullptr);
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("Mesh_CrossSections"),
widget->windowTitle(),
true,
nullptr);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}

View File

@@ -31,28 +31,37 @@
#include <Gui/TaskView/TaskView.h>
namespace Gui {
namespace Gui
{
class View3DInventor;
}
namespace MeshPartGui {
namespace MeshPartGui
{
class ViewProviderCrossSections;
class Ui_CrossSections;
class CrossSections : public QDialog
class CrossSections: public QDialog
{
Q_OBJECT
enum Plane { XY, XZ, YZ };
enum Plane
{
XY,
XZ,
YZ
};
public:
explicit CrossSections(const Base::BoundBox3d& bb, QWidget* parent = nullptr, Qt::WindowFlags fl = Qt::WindowFlags());
explicit CrossSections(const Base::BoundBox3d& bb,
QWidget* parent = nullptr,
Qt::WindowFlags fl = Qt::WindowFlags());
~CrossSections() override;
void accept() override;
void apply();
protected:
void changeEvent(QEvent *e) override;
void changeEvent(QEvent* e) override;
void keyPressEvent(QKeyEvent*) override;
private:
@@ -69,7 +78,7 @@ private:
private:
std::vector<double> getPlanes() const;
void calcPlane(Plane, double);
void calcPlanes(Plane/*, double, bool, int*/);
void calcPlanes(Plane /*, double, bool, int*/);
void makePlanes(Plane, const std::vector<double>&, double[4]);
Plane plane() const;
@@ -80,7 +89,7 @@ private:
QPointer<Gui::View3DInventor> view;
};
class TaskCrossSections : public Gui::TaskView::TaskDialog
class TaskCrossSections: public Gui::TaskView::TaskDialog
{
Q_OBJECT
@@ -92,13 +101,15 @@ public:
void clicked(int id) override;
QDialogButtonBox::StandardButtons getStandardButtons() const override
{ return QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel; }
{
return QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel;
}
private:
CrossSections* widget;
Gui::TaskView::TaskBox* taskbox;
};
} // namespace MeshPartGui
}// namespace MeshPartGui
#endif // MESHPARTGUI_CROSSSECTIONS_H
#endif// MESHPARTGUI_CROSSSECTIONS_H

View File

@@ -23,32 +23,32 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QMenu>
# include <QPointer>
# include <QStatusBar>
# include <QTimer>
#include <QMenu>
#include <QPointer>
#include <QStatusBar>
#include <QTimer>
# include <gp_Pnt.hxx>
# include <TColgp_Array1OfPnt.hxx>
# include <GeomAPI_PointsToBSpline.hxx>
# include <Geom_BSplineCurve.hxx>
# include <BRep_Tool.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepBuilderAPI_MakePolygon.hxx>
# include <BRepMesh_IncrementalMesh.hxx>
# include <Poly_Polygon3D.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Wire.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Tool.hxx>
#include <GeomAPI_PointsToBSpline.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Poly_Polygon3D.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <gp_Pnt.hxx>
# include <Inventor/SoPickedPoint.h>
# include <Inventor/details/SoFaceDetail.h>
# include <Inventor/events/SoMouseButtonEvent.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoCoordinate3.h>
# include <Inventor/nodes/SoDrawStyle.h>
# include <Inventor/nodes/SoLineSet.h>
# include <Inventor/nodes/SoPointSet.h>
# include <Inventor/nodes/SoSeparator.h>
#include <Inventor/SoPickedPoint.h>
#include <Inventor/details/SoFaceDetail.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/nodes/SoBaseColor.h>
#include <Inventor/nodes/SoCoordinate3.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoLineSet.h>
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/nodes/SoSeparator.h>
#endif
#include <App/Document.h>
@@ -58,11 +58,11 @@
#include <Gui/Utilities.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Mod/Mesh/App/MeshFeature.h>
#include <Mod/Mesh/App/Core/Algorithm.h>
#include <Mod/Mesh/App/Core/Grid.h>
#include <Mod/Mesh/App/Core/MeshKernel.h>
#include <Mod/Mesh/App/Core/Projection.h>
#include <Mod/Mesh/App/MeshFeature.h>
#include <Mod/Mesh/Gui/ViewProvider.h>
#include <Mod/Part/App/PartFeature.h>
@@ -80,9 +80,9 @@
#endif
/* XPM */
static const char *cursor_curveonmesh[]={
// clang-format off
static const char* cursor_curveonmesh[] = {
"32 32 3 1",
"+ c white",
"# c red",
@@ -119,6 +119,7 @@ static const char *cursor_curveonmesh[]={
"................................",
"................................",
"................................"};
// clang-format on
using namespace MeshPartGui;
@@ -138,7 +139,7 @@ ViewProviderCurveOnMesh::ViewProviderCurveOnMesh()
SoGroup* pcLineRoot = new SoSeparator();
pcLineRoot->addChild(pcLinesStyle);
SoBaseColor * linecol = new SoBaseColor;
SoBaseColor* linecol = new SoBaseColor;
linecol->rgb.setValue(1.0f, 1.0f, 0.0f);
pcLineRoot->addChild(linecol);
pcLineRoot->addChild(pcCoords);
@@ -156,7 +157,7 @@ ViewProviderCurveOnMesh::ViewProviderCurveOnMesh()
SoGroup* pcPointRoot = new SoSeparator();
pcPointRoot->addChild(pcPointStyle);
SoBaseColor * pointcol = new SoBaseColor;
SoBaseColor* pointcol = new SoBaseColor;
pointcol->rgb.setValue(1.0f, 0.5f, 0.0f);
pcPointRoot->addChild(pointcol);
pcPointRoot->addChild(pcNodes);
@@ -231,7 +232,8 @@ public:
int maxDegree;
GeomAbs_Shape cont;
ApproxPar() {
ApproxPar()
{
weight1 = 0.2;
weight2 = 0.4;
weight3 = 0.2;
@@ -243,14 +245,13 @@ public:
Private()
: curve(new ViewProviderCurveOnMesh)
, editcursor(QPixmap(cursor_curveonmesh), 7, 7)
{
}
{}
~Private()
{
delete curve;
delete grid;
}
static void vertexCallback(void * ud, SoEventCallback * n);
static void vertexCallback(void* ud, SoEventCallback* n);
std::vector<SbVec3f> convert(const std::vector<Base::Vector3f>& points) const
{
std::vector<SbVec3f> pts;
@@ -279,7 +280,8 @@ public:
MeshCore::MeshProjection meshProjection(kernel);
Base::Vector3f v1 = Base::convertTo<Base::Vector3f>(last.point);
Base::Vector3f v2 = Base::convertTo<Base::Vector3f>(pick.point);
Base::Vector3f vd = Base::convertTo<Base::Vector3f>(viewer->getViewer()->getViewDirection());
Base::Vector3f vd =
Base::convertTo<Base::Vector3f>(viewer->getViewer()->getViewDirection());
if (meshProjection.projectLineOnMesh(*grid, v1, last.facet, v2, pick.facet, vd, polyline)) {
if (polyline.size() > 1) {
if (cutLines.empty()) {
@@ -291,7 +293,7 @@ public:
dir2.normalize();
std::size_t num = pickedPoints.size();
if (num >= 2) {
dir1 = pickedPoints[num-1].point - pickedPoints[num-2].point;
dir1 = pickedPoints[num - 1].point - pickedPoints[num - 2].point;
dir1.normalize();
}
@@ -302,7 +304,7 @@ public:
}
else {
std::vector<Base::Vector3f>& segm = cutLines.back();
segm.insert(segm.end(), polyline.begin()+1, polyline.end());
segm.insert(segm.end(), polyline.begin() + 1, polyline.end());
}
}
@@ -314,14 +316,14 @@ public:
}
std::vector<PickedPoint> pickedPoints;
std::list<std::vector<Base::Vector3f> > cutLines;
bool wireClosed{false};
double distance{1};
double cosAngle{0.7071}; // 45 degree
bool approximate{true};
std::list<std::vector<Base::Vector3f>> cutLines;
bool wireClosed {false};
double distance {1};
double cosAngle {0.7071};// 45 degree
bool approximate {true};
ViewProviderCurveOnMesh* curve;
Gui::ViewProviderDocumentObject* mesh{0};
MeshCore::MeshFacetGrid* grid{nullptr};
Gui::ViewProviderDocumentObject* mesh {0};
MeshCore::MeshFacetGrid* grid {nullptr};
MeshCore::MeshKernel kernel;
QPointer<Gui::View3DInventor> viewer;
QCursor editcursor;
@@ -329,9 +331,9 @@ public:
};
CurveOnMeshHandler::CurveOnMeshHandler(QObject* parent)
: QObject(parent), d_ptr(new Private)
{
}
: QObject(parent)
, d_ptr(new Private)
{}
CurveOnMeshHandler::~CurveOnMeshHandler()
{
@@ -343,7 +345,10 @@ void CurveOnMeshHandler::enableApproximation(bool on)
d_ptr->approximate = on;
}
void CurveOnMeshHandler::setParameters(int maxDegree, GeomAbs_Shape cont, double tol3d, double angle)
void CurveOnMeshHandler::setParameters(int maxDegree,
GeomAbs_Shape cont,
double tol3d,
double angle)
{
d_ptr->par.maxDegree = maxDegree;
d_ptr->par.cont = cont;
@@ -369,13 +374,15 @@ void CurveOnMeshHandler::onCreate()
std::vector<SbVec3f> segm = d_ptr->convert(*it);
if (d_ptr->approximate) {
Handle(Geom_BSplineCurve) spline = approximateSpline(segm);
if (!spline.IsNull())
if (!spline.IsNull()) {
displaySpline(spline);
}
}
else {
TopoDS_Wire wire;
if (makePolyline(segm, wire))
if (makePolyline(segm, wire)) {
displayPolyline(wire);
}
}
}
@@ -450,8 +457,9 @@ std::vector<SbVec3f> CurveOnMeshHandler::getVertexes() const
{
std::vector<SbVec3f> pts;
pts.reserve(d_ptr->pickedPoints.size());
for (const auto & it : d_ptr->pickedPoints)
for (const auto& it : d_ptr->pickedPoints) {
pts.push_back(it.point);
}
return pts;
}
@@ -467,19 +475,24 @@ std::vector<SbVec3f> CurveOnMeshHandler::getPoints() const
Handle(Geom_BSplineCurve) CurveOnMeshHandler::approximateSpline(const std::vector<SbVec3f>& points)
{
TColgp_Array1OfPnt pnts(1,points.size());
TColgp_Array1OfPnt pnts(1, points.size());
Standard_Integer index = 1;
for (const auto& it : points) {
float x,y,z;
it.getValue(x,y,z);
pnts(index++) = gp_Pnt(x,y,z);
float x, y, z;
it.getValue(x, y, z);
pnts(index++) = gp_Pnt(x, y, z);
}
try {
//GeomAPI_PointsToBSpline fit(pnts, 1, 2, GeomAbs_C0, 1.0e-3);
//GeomAPI_PointsToBSpline fit(pnts, d_ptr->par.weight1, d_ptr->par.weight2, d_ptr->par.weight3,
// d_ptr->par.maxDegree, d_ptr->par.cont, d_ptr->par.tol3d);
GeomAPI_PointsToBSpline fit(pnts, 1, d_ptr->par.maxDegree, d_ptr->par.cont, d_ptr->par.tol3d);
// GeomAPI_PointsToBSpline fit(pnts, 1, 2, GeomAbs_C0, 1.0e-3);
// GeomAPI_PointsToBSpline fit(pnts, d_ptr->par.weight1, d_ptr->par.weight2,
// d_ptr->par.weight3,
// d_ptr->par.maxDegree, d_ptr->par.cont, d_ptr->par.tol3d);
GeomAPI_PointsToBSpline fit(pnts,
1,
d_ptr->par.maxDegree,
d_ptr->par.cont,
d_ptr->par.tol3d);
Handle(Geom_BSplineCurve) spline = fit.Curve();
return spline;
}
@@ -498,18 +511,18 @@ void CurveOnMeshHandler::approximateEdge(const TopoDS_Edge& edge, double toleran
const TColgp_Array1OfPnt& aNodes = aPoly->Nodes();
std::vector<SbVec3f> pts;
pts.reserve(numNodes);
for (int i=aNodes.Lower(); i<=aNodes.Upper(); i++) {
for (int i = aNodes.Lower(); i <= aNodes.Upper(); i++) {
const gp_Pnt& p = aNodes.Value(i);
pts.emplace_back(static_cast<float>(p.X()),
static_cast<float>(p.Y()),
static_cast<float>(p.Z()));
static_cast<float>(p.Y()),
static_cast<float>(p.Z()));
}
d_ptr->curve->setPoints(pts);
}
}
void CurveOnMeshHandler::displaySpline(const Handle(Geom_BSplineCurve)& spline)
void CurveOnMeshHandler::displaySpline(const Handle(Geom_BSplineCurve) & spline)
{
if (d_ptr->viewer) {
double u = spline->FirstParameter();
@@ -530,9 +543,9 @@ bool CurveOnMeshHandler::makePolyline(const std::vector<SbVec3f>& points, TopoDS
{
BRepBuilderAPI_MakePolygon mkPoly;
for (const auto& it : points) {
float x,y,z;
it.getValue(x,y,z);
mkPoly.Add(gp_Pnt(x,y,z));
float x, y, z;
it.getValue(x, y, z);
mkPoly.Add(gp_Pnt(x, y, z));
}
if (mkPoly.IsDone()) {
@@ -549,7 +562,8 @@ void CurveOnMeshHandler::displayPolyline(const TopoDS_Wire& wire)
Gui::View3DInventorViewer* view3d = d_ptr->viewer->getViewer();
App::Document* doc = view3d->getDocument()->getDocument();
doc->openTransaction("Add polyline");
Part::Feature* part = static_cast<Part::Feature*>(doc->addObject("Part::Feature", "Polyline"));
Part::Feature* part =
static_cast<Part::Feature*>(doc->addObject("Part::Feature", "Polyline"));
part->Shape.setValue(wire);
doc->commitTransaction();
}
@@ -579,23 +593,27 @@ void CurveOnMeshHandler::closeWire()
}
}
void CurveOnMeshHandler::Private::vertexCallback(void * ud, SoEventCallback * cb)
void CurveOnMeshHandler::Private::vertexCallback(void* ud, SoEventCallback* cb)
{
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(cb->getUserData());
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(cb->getUserData());
const SoEvent* ev = cb->getEvent();
if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
// set as handled
cb->setHandled();
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ev);
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
const SoPickedPoint * pp = cb->getPickedPoint();
const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(ev);
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1
&& mbe->getState() == SoButtonEvent::DOWN) {
const SoPickedPoint* pp = cb->getPickedPoint();
if (pp) {
CurveOnMeshHandler* self = static_cast<CurveOnMeshHandler*>(ud);
if (!self->d_ptr->wireClosed) {
Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(pp->getPath());
if (vp && vp->getTypeId().isDerivedFrom(MeshGui::ViewProviderMesh::getClassTypeId())) {
MeshGui::ViewProviderMesh* mesh = static_cast<MeshGui::ViewProviderMesh*>(vp);
if (vp
&& vp->getTypeId().isDerivedFrom(
MeshGui::ViewProviderMesh::getClassTypeId())) {
MeshGui::ViewProviderMesh* mesh =
static_cast<MeshGui::ViewProviderMesh*>(vp);
const SoDetail* detail = pp->getDetail();
if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
// get the mesh and build a grid
@@ -635,7 +653,9 @@ void CurveOnMeshHandler::Private::vertexCallback(void * ud, SoEventCallback * cb
}
}
// try to 'complete' the curve
else if (vp && vp->getTypeId().isDerivedFrom(ViewProviderCurveOnMesh::getClassTypeId())) {
else if (vp
&& vp->getTypeId().isDerivedFrom(
ViewProviderCurveOnMesh::getClassTypeId())) {
const SbVec3f& p = pp->getPoint();
if (self->tryCloseWire(p)) {
self->closeWire();
@@ -644,11 +664,11 @@ void CurveOnMeshHandler::Private::vertexCallback(void * ud, SoEventCallback * cb
}
}
else {
Gui::getMainWindow()->statusBar()->showMessage(
tr("No point was picked"));
Gui::getMainWindow()->statusBar()->showMessage(tr("No point was picked"));
}
}
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2
&& mbe->getState() == SoButtonEvent::UP) {
CurveOnMeshHandler* self = static_cast<CurveOnMeshHandler*>(ud);
QTimer::singleShot(100, self, &CurveOnMeshHandler::onContextMenu);
}

View File

@@ -23,10 +23,10 @@
#ifndef MESHPARTGUI_CURVEONMESH_H
#define MESHPARTGUI_CURVEONMESH_H
#include <memory>
#include <QObject>
#include <Geom_BSplineCurve.hxx>
#include <GeomAbs_Shape.hxx>
#include <Geom_BSplineCurve.hxx>
#include <QObject>
#include <memory>
#include <Gui/ViewProviderDocumentObject.h>
@@ -37,15 +37,16 @@ class SoDrawStyle;
class TopoDS_Edge;
class TopoDS_Wire;
namespace Gui {
namespace Gui
{
class View3DInventor;
class ViewProvider;
}
}// namespace Gui
namespace MeshPartGui
{
class ViewProviderCurveOnMesh : public Gui::ViewProviderDocumentObject
class ViewProviderCurveOnMesh: public Gui::ViewProviderDocumentObject
{
PROPERTY_HEADER_WITH_OVERRIDE(MeshPartGui::ViewProviderCurveOnMesh);
@@ -59,13 +60,13 @@ public:
void setDisplayMode(const char* ModeName) override;
private:
SoCoordinate3 * pcCoords;
SoCoordinate3 * pcNodes;
SoDrawStyle * pcPointStyle;
SoDrawStyle * pcLinesStyle;
SoCoordinate3* pcCoords;
SoCoordinate3* pcNodes;
SoDrawStyle* pcPointStyle;
SoDrawStyle* pcLinesStyle;
};
class CurveOnMeshHandler : public QObject
class CurveOnMeshHandler: public QObject
{
Q_OBJECT
@@ -81,7 +82,7 @@ public:
private:
Handle(Geom_BSplineCurve) approximateSpline(const std::vector<SbVec3f>& points);
void approximateEdge(const TopoDS_Edge&, double tolerance);
void displaySpline(const Handle(Geom_BSplineCurve)&);
void displaySpline(const Handle(Geom_BSplineCurve) &);
bool makePolyline(const std::vector<SbVec3f>& points, TopoDS_Wire& wire);
void displayPolyline(const TopoDS_Wire& wire);
std::vector<SbVec3f> getPoints() const;
@@ -101,6 +102,6 @@ private:
std::unique_ptr<Private> d_ptr;
};
}
}// namespace MeshPartGui
#endif // MESHPARTGUI_CURVEONMESH_H
#endif// MESHPARTGUI_CURVEONMESH_H

View File

@@ -1,24 +1,24 @@
#***************************************************************************
#* Copyright (c) 2017 Lorenz Lechner *
#* *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This library is free software; you can redistribute it and/or *
#* modify it under the terms of the GNU Library General Public *
#* License as published by the Free Software Foundation; either *
#* version 2 of the License, or (at your option) any later version. *
#* *
#* This library is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this library; see the file COPYING.LIB. If not, *
#* write to the Free Software Foundation, Inc., 59 Temple Place, *
#* Suite 330, Boston, MA 02111-1307, USA *
#* *
#***************************************************************************/
# ***************************************************************************
# * Copyright (c) 2017 Lorenz Lechner *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This library is free software; you can redistribute it and/or *
# * modify it under the terms of the GNU Library General Public *
# * License as published by the Free Software Foundation; either *
# * version 2 of the License, or (at your option) any later version. *
# * *
# * This library is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this library; see the file COPYING.LIB. If not, *
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
# * Suite 330, Boston, MA 02111-1307, USA *
# * *
# ***************************************************************************/
import Mesh
import FreeCAD as App
@@ -26,7 +26,8 @@ import FreeCADGui as Gui
import Part
import MeshPartGui
from PySide.QtCore import QT_TRANSLATE_NOOP # for translations
from PySide.QtCore import QT_TRANSLATE_NOOP # for translations
class BaseCommand(object):
def __init__(self):
@@ -43,21 +44,28 @@ class CreateFlatMesh(BaseCommand):
"""create flat wires from a meshed face"""
def GetResources(self):
return {'Pixmap': 'MeshPart_CreateFlatMesh.svg',
'MenuText': QT_TRANSLATE_NOOP("MeshPart_CreateFlatMesh", "Unwrap Mesh"),
'ToolTip': QT_TRANSLATE_NOOP("MeshPart_CreateFlatMesh", "Find a flat representation of a mesh.")}
return {
"Pixmap": "MeshPart_CreateFlatMesh.svg",
"MenuText": QT_TRANSLATE_NOOP("MeshPart_CreateFlatMesh", "Unwrap Mesh"),
"ToolTip": QT_TRANSLATE_NOOP(
"MeshPart_CreateFlatMesh", "Find a flat representation of a mesh."
),
}
def Activated(self):
import numpy as np
import flatmesh
obj = Gui.Selection.getSelection()[0] # obj must be a Mesh (Mesh-Design->Meshes->Create-Mesh)
obj = Gui.Selection.getSelection()[
0
] # obj must be a Mesh (Mesh-Design->Meshes->Create-Mesh)
points = np.array([[i.x, i.y, i.z] for i in obj.Mesh.Points])
faces = np.array([list(i) for i in obj.Mesh.Topology[1]])
faces = np.array([list(i) for i in obj.Mesh.Topology[1]])
flattener = flatmesh.FaceUnwrapper(points, faces)
flattener.findFlatNodes(5, 0.95)
boundaries = flattener.getFlatBoundaryNodes()
#print('number of nodes: {}'.format(len(flattener.ze_nodes)))
#print('number of faces: {}'.format(len(flattener.tris)))
# print('number of nodes: {}'.format(len(flattener.ze_nodes)))
# print('number of faces: {}'.format(len(flattener.tris)))
wires = []
for edge in boundaries:
@@ -65,23 +73,28 @@ class CreateFlatMesh(BaseCommand):
Part.show(Part.Wire(pi))
def IsActive(self):
assert(super(CreateFlatMesh, self).IsActive())
assert(isinstance(Gui.Selection.getSelection()[0].Mesh, Mesh.Mesh))
assert super(CreateFlatMesh, self).IsActive()
assert isinstance(Gui.Selection.getSelection()[0].Mesh, Mesh.Mesh)
return True
class CreateFlatFace(BaseCommand):
"""create a flat face from a single face
only full faces are supported right now"""
only full faces are supported right now"""
def GetResources(self):
return {'Pixmap': 'MeshPart_CreateFlatFace.svg',
'MenuText': QT_TRANSLATE_NOOP("MeshPart_CreateFlatFace", "Unwrap Face"),
'ToolTip': QT_TRANSLATE_NOOP("MeshPart_CreateFlatFace", "Find a flat representation of a face.")}
return {
"Pixmap": "MeshPart_CreateFlatFace.svg",
"MenuText": QT_TRANSLATE_NOOP("MeshPart_CreateFlatFace", "Unwrap Face"),
"ToolTip": QT_TRANSLATE_NOOP(
"MeshPart_CreateFlatFace", "Find a flat representation of a face."
),
}
def Activated(self):
import numpy as np
import flatmesh
face = Gui.Selection.getSelectionEx()[0].SubObjects[0]
shape = face.toNurbs()
face = shape.Faces[0]
@@ -104,16 +117,17 @@ class CreateFlatFace(BaseCommand):
Part.show(bs.toShape())
def IsActive(self):
assert(super(CreateFlatFace, self).IsActive())
assert(isinstance(Gui.Selection.getSelectionEx()[0].SubObjects[0], Part.Face))
assert super(CreateFlatFace, self).IsActive()
assert isinstance(Gui.Selection.getSelectionEx()[0].SubObjects[0], Part.Face)
return True
# Test if pybind11 dependency is available
try:
import flatmesh
Gui.addCommand('MeshPart_CreateFlatMesh', CreateFlatMesh())
Gui.addCommand('MeshPart_CreateFlatFace', CreateFlatFace())
Gui.addCommand("MeshPart_CreateFlatMesh", CreateFlatMesh())
Gui.addCommand("MeshPart_CreateFlatFace", CreateFlatFace())
except ImportError:
App.Console.PrintLog("flatmesh-commands are not available\n")
App.Console.PrintLog("flatmesh needs pybind11 as build dependency\n")

View File

@@ -26,9 +26,9 @@
#include <FCConfig.h>
#ifdef _MSC_VER
# pragma warning(disable : 4005)
# pragma warning(disable : 4290)
# pragma warning(disable : 4275)
#pragma warning(disable : 4005)
#pragma warning(disable : 4290)
#pragma warning(disable : 4275)
#endif
#ifdef _PreComp_
@@ -40,31 +40,30 @@
// Qt Toolkit
#include <QApplication>
#include <QFuture>
#include <QMenu>
#include <QMessageBox>
#include <QKeyEvent>
#include <QMenu>
#include <QMessageBox>
#include <QPointer>
#include <QPushButton>
#include <QStatusBar>
#include <QtConcurrentMap>
#include <QTimer>
#include <QtConcurrentMap>
// OCCT
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <Geom_BSplineCurve.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <GeomAPI_PointsToBSpline.hxx>
#include <gp_Pnt.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Poly_Polygon3D.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <gp_Pnt.hxx>
// Inventor
#include <Inventor/SoPickedPoint.h>
@@ -77,6 +76,6 @@
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/nodes/SoSeparator.h>
#endif //_PreComp_
#endif//_PreComp_
#endif // __PRECOMPILED_GUI__
#endif// __PRECOMPILED_GUI__

View File

@@ -24,9 +24,9 @@
#include <Gui/View3DInventor.h>
#include "CurveOnMesh.h"
#include "TaskCurveOnMesh.h"
#include "ui_TaskCurveOnMesh.h"
#include "CurveOnMesh.h"
using namespace MeshPartGui;
@@ -38,8 +38,7 @@ CurveOnMeshWidget::CurveOnMeshWidget(Gui::View3DInventor* view, QWidget* parent)
, myView(view)
{
ui->setupUi(this);
connect(ui->startButton, &QPushButton::clicked,
this, &CurveOnMeshWidget::onStartButtonClicked);
connect(ui->startButton, &QPushButton::clicked, this, &CurveOnMeshWidget::onStartButtonClicked);
this->setup();
}
@@ -61,12 +60,13 @@ void CurveOnMeshWidget::setup()
ui->continuity->addItem(QString::fromLatin1("C3"), static_cast<int>(GeomAbs_C3));
ui->continuity->setCurrentIndex(2);
for (int i=0; i<8; i++)
ui->maxDegree->addItem(QString::number(i+1));
for (int i = 0; i < 8; i++) {
ui->maxDegree->addItem(QString::number(i + 1));
}
ui->maxDegree->setCurrentIndex(4);
}
void CurveOnMeshWidget::changeEvent(QEvent *e)
void CurveOnMeshWidget::changeEvent(QEvent* e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
@@ -97,9 +97,7 @@ void CurveOnMeshWidget::reject()
TaskCurveOnMesh::TaskCurveOnMesh(Gui::View3DInventor* view)
{
widget = new CurveOnMeshWidget(view);
taskbox = new Gui::TaskView::TaskBox(
QPixmap(),
widget->windowTitle(), true, nullptr);
taskbox = new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(), true, nullptr);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}

View File

@@ -29,7 +29,8 @@
#include <Gui/TaskView/TaskView.h>
namespace Gui {
namespace Gui
{
class View3DInventor;
}
@@ -39,18 +40,18 @@ namespace MeshPartGui
class Ui_TaskCurveOnMesh;
class CurveOnMeshHandler;
class CurveOnMeshWidget : public QWidget
class CurveOnMeshWidget: public QWidget
{
Q_OBJECT
public:
explicit CurveOnMeshWidget(Gui::View3DInventor* view, QWidget* parent=nullptr);
explicit CurveOnMeshWidget(Gui::View3DInventor* view, QWidget* parent = nullptr);
~CurveOnMeshWidget() override;
void reject();
protected:
void changeEvent(QEvent *e) override;
void changeEvent(QEvent* e) override;
void setup();
private:
@@ -62,7 +63,7 @@ private:
QPointer<Gui::View3DInventor> myView;
};
class TaskCurveOnMesh : public Gui::TaskView::TaskDialog
class TaskCurveOnMesh: public Gui::TaskView::TaskDialog
{
Q_OBJECT
@@ -73,13 +74,15 @@ public:
bool reject() override;
QDialogButtonBox::StandardButtons getStandardButtons() const override
{ return QDialogButtonBox::Close; }
{
return QDialogButtonBox::Close;
}
private:
CurveOnMeshWidget* widget;
Gui::TaskView::TaskBox* taskbox;
};
} //namespace MeshPartGui
}// namespace MeshPartGui
#endif // MESHPART_GUI_TASKCURVEONMESH_H
#endif// MESHPART_GUI_TASKCURVEONMESH_H

View File

@@ -22,15 +22,15 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QMessageBox>
#include <QMessageBox>
#endif
#include <App/Application.h>
#include <App/Document.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Stream.h>
#include <Base/Tools.h>
#include <App/Application.h>
#include <App/Document.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
@@ -39,8 +39,8 @@
#include <Gui/Selection.h>
#include <Gui/WaitCursor.h>
#include <Mod/Mesh/App/MeshFeature.h>
#include <Mod/Part/App/BodyBase.h>
#include <Mod/Mesh/Gui/ViewProvider.h>
#include <Mod/Part/App/BodyBase.h>
#include <Mod/Part/Gui/ViewProvider.h>
#include "Tessellation.h"
@@ -52,7 +52,8 @@ using namespace MeshPartGui;
/* TRANSLATOR MeshPartGui::Tessellation */
Tessellation::Tessellation(QWidget* parent)
: QWidget(parent), ui(new Ui_Tessellation)
: QWidget(parent)
, ui(new Ui_Tessellation)
{
ui->setupUi(this);
gmsh = new Mesh2ShapeGmsh(this);
@@ -60,8 +61,8 @@ Tessellation::Tessellation(QWidget* parent)
ui->stackedWidget->addTab(gmsh, tr("Gmsh"));
ParameterGrp::handle handle = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Mod/Mesh/Meshing/Standard");
ParameterGrp::handle handle = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Mesh/Meshing/Standard");
double value = ui->spinSurfaceDeviation->value().getValue();
value = handle->GetFloat("LinearDeflection", value);
double angle = ui->spinAngularDeviation->value().getValue();
@@ -79,10 +80,10 @@ Tessellation::Tessellation(QWidget* parent)
ui->comboFineness->setCurrentIndex(2);
onComboFinenessCurrentIndexChanged(2);
#if !defined (HAVE_MEFISTO)
#if !defined(HAVE_MEFISTO)
ui->stackedWidget->setTabEnabled(Mefisto, false);
#endif
#if !defined (HAVE_NETGEN)
#if !defined(HAVE_NETGEN)
ui->stackedWidget->setTabEnabled(Netgen, false);
#endif
@@ -101,14 +102,22 @@ Tessellation::~Tessellation() = default;
void Tessellation::setupConnections()
{
connect(gmsh, &Mesh2ShapeGmsh::processed, this, &Tessellation::gmshProcessed);
connect(ui->estimateMaximumEdgeLength, &QPushButton::clicked,
this, &Tessellation::onEstimateMaximumEdgeLengthClicked);
connect(ui->comboFineness, qOverload<int>(&QComboBox::currentIndexChanged),
this, &Tessellation::onComboFinenessCurrentIndexChanged);
connect(ui->checkSecondOrder, &QCheckBox::toggled,
this, &Tessellation::onCheckSecondOrderToggled);
connect(ui->checkQuadDominated, &QCheckBox::toggled,
this, &Tessellation::onCheckQuadDominatedToggled);
connect(ui->estimateMaximumEdgeLength,
&QPushButton::clicked,
this,
&Tessellation::onEstimateMaximumEdgeLengthClicked);
connect(ui->comboFineness,
qOverload<int>(&QComboBox::currentIndexChanged),
this,
&Tessellation::onComboFinenessCurrentIndexChanged);
connect(ui->checkSecondOrder,
&QCheckBox::toggled,
this,
&Tessellation::onCheckSecondOrderToggled);
connect(ui->checkQuadDominated,
&QCheckBox::toggled,
this,
&Tessellation::onCheckQuadDominatedToggled);
}
void Tessellation::meshingMethod(int id)
@@ -130,56 +139,59 @@ void Tessellation::onComboFinenessCurrentIndexChanged(int index)
}
switch (index) {
case VeryCoarse:
ui->doubleGrading->setValue(0.7);
ui->spinEdgeElements->setValue(0.3);
ui->spinCurvatureElements->setValue(1.0);
break;
case Coarse:
ui->doubleGrading->setValue(0.5);
ui->spinEdgeElements->setValue(0.5);
ui->spinCurvatureElements->setValue(1.5);
break;
case Moderate:
ui->doubleGrading->setValue(0.3);
ui->spinEdgeElements->setValue(1.0);
ui->spinCurvatureElements->setValue(2.0);
break;
case Fine:
ui->doubleGrading->setValue(0.2);
ui->spinEdgeElements->setValue(2.0);
ui->spinCurvatureElements->setValue(3.0);
break;
case VeryFine:
ui->doubleGrading->setValue(0.1);
ui->spinEdgeElements->setValue(3.0);
ui->spinCurvatureElements->setValue(5.0);
break;
default:
break;
case VeryCoarse:
ui->doubleGrading->setValue(0.7);
ui->spinEdgeElements->setValue(0.3);
ui->spinCurvatureElements->setValue(1.0);
break;
case Coarse:
ui->doubleGrading->setValue(0.5);
ui->spinEdgeElements->setValue(0.5);
ui->spinCurvatureElements->setValue(1.5);
break;
case Moderate:
ui->doubleGrading->setValue(0.3);
ui->spinEdgeElements->setValue(1.0);
ui->spinCurvatureElements->setValue(2.0);
break;
case Fine:
ui->doubleGrading->setValue(0.2);
ui->spinEdgeElements->setValue(2.0);
ui->spinCurvatureElements->setValue(3.0);
break;
case VeryFine:
ui->doubleGrading->setValue(0.1);
ui->spinEdgeElements->setValue(3.0);
ui->spinCurvatureElements->setValue(5.0);
break;
default:
break;
}
}
void Tessellation::onCheckSecondOrderToggled(bool on)
{
if (on)
if (on) {
ui->checkQuadDominated->setChecked(false);
}
}
void Tessellation::onCheckQuadDominatedToggled(bool on)
{
if (on)
if (on) {
ui->checkSecondOrder->setChecked(false);
}
}
void Tessellation::gmshProcessed()
{
bool doClose = !ui->checkBoxDontQuit->isChecked();
if (doClose)
if (doClose) {
Gui::Control().reject();
}
}
void Tessellation::changeEvent(QEvent *e)
void Tessellation::changeEvent(QEvent* e)
{
if (e->type() == QEvent::LanguageChange) {
int index = ui->comboFineness->currentIndex();
@@ -202,8 +214,8 @@ void Tessellation::onEstimateMaximumEdgeLengthClicked()
}
double edgeLen = 0;
for (auto &sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) {
auto shape = Part::Feature::getTopoShape(sel.pObject,sel.SubName);
for (auto& sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) {
auto shape = Part::Feature::getTopoShape(sel.pObject, sel.SubName);
if (shape.hasSubShape(TopAbs_FACE)) {
Base::BoundBox3d bbox = shape.getBoundBox();
edgeLen = std::max<double>(edgeLen, bbox.LengthX());
@@ -212,7 +224,7 @@ void Tessellation::onEstimateMaximumEdgeLengthClicked()
}
}
ui->spinMaximumEdgeLength->setValue(edgeLen/10);
ui->spinMaximumEdgeLength->setValue(edgeLen / 10);
}
bool Tessellation::accept()
@@ -234,8 +246,8 @@ bool Tessellation::accept()
bool bodyWithNoTip = false;
bool partWithNoFace = false;
for (auto &sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) {
auto shape = Part::Feature::getTopoShape(sel.pObject,sel.SubName);
for (auto& sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) {
auto shape = Part::Feature::getTopoShape(sel.pObject, sel.SubName);
if (shape.hasSubShape(TopAbs_FACE)) {
shapeObjects.emplace_back(sel.pObject, sel.SubName);
}
@@ -254,12 +266,17 @@ bool Tessellation::accept()
if (shapeObjects.empty()) {
if (bodyWithNoTip) {
QMessageBox::critical(this, windowTitle(), tr("You have selected a body without tip.\n"
"Either set the tip of the body or select a different shape, please."));
QMessageBox::critical(
this,
windowTitle(),
tr("You have selected a body without tip.\n"
"Either set the tip of the body or select a different shape, please."));
}
else if (partWithNoFace) {
QMessageBox::critical(this, windowTitle(), tr("You have selected a shape without faces.\n"
"Select a different shape, please."));
QMessageBox::critical(this,
windowTitle(),
tr("You have selected a shape without faces.\n"
"Select a different shape, please."));
}
else {
QMessageBox::critical(this, windowTitle(), tr("Select a shape for meshing, first."));
@@ -282,7 +299,9 @@ bool Tessellation::accept()
}
}
void Tessellation::process(int method, App::Document* doc, const std::list<App::SubObjectT>& shapeObjects)
void Tessellation::process(int method,
App::Document* doc,
const std::list<App::SubObjectT>& shapeObjects)
{
try {
Gui::WaitCursor wc;
@@ -290,37 +309,36 @@ void Tessellation::process(int method, App::Document* doc, const std::list<App::
saveParameters(method);
doc->openTransaction("Meshing");
for (auto &info : shapeObjects) {
for (auto& info : shapeObjects) {
QString subname = QString::fromLatin1(info.getSubName().c_str());
QString objname = QString::fromLatin1(info.getObjectName().c_str());
auto obj = info.getObject();
if (!obj)
if (!obj) {
continue;
}
auto sobj = obj->getSubObject(info.getSubName().c_str());
if (!sobj)
if (!sobj) {
continue;
}
sobj = sobj->getLinkedObject(true);
if (!sobj)
if (!sobj) {
continue;
}
QString label = QString::fromUtf8(sobj->Label.getValue());
QString param = getMeshingParameters(method, sobj);
QString cmd = QString::fromLatin1(
"__doc__=FreeCAD.getDocument(\"%1\")\n"
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
"__part__=__doc__.getObject(\"%2\")\n"
"__shape__=Part.getShape(__part__,\"%3\")\n"
"__mesh__.Mesh=MeshPart.meshFromShape(%4)\n"
"__mesh__.Label=\"%5 (Meshed)\"\n"
"del __doc__, __mesh__, __part__, __shape__\n")
.arg(this->document,
objname,
subname,
param,
label);
QString cmd =
QString::fromLatin1("__doc__=FreeCAD.getDocument(\"%1\")\n"
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
"__part__=__doc__.getObject(\"%2\")\n"
"__shape__=Part.getShape(__part__,\"%3\")\n"
"__mesh__.Mesh=MeshPart.meshFromShape(%4)\n"
"__mesh__.Label=\"%5 (Meshed)\"\n"
"del __doc__, __mesh__, __part__, __shape__\n")
.arg(this->document, objname, subname, param, label);
Gui::Command::runCommand(Gui::Command::Doc, cmd.toUtf8());
@@ -337,8 +355,8 @@ void Tessellation::process(int method, App::Document* doc, const std::list<App::
void Tessellation::saveParameters(int method)
{
if (method == Standard) {
ParameterGrp::handle handle = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Mod/Mesh/Meshing/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();
@@ -353,12 +371,12 @@ void Tessellation::setFaceColors(int method, App::Document* doc, App::DocumentOb
// 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());
Gui::ViewProvider* vpm =
Gui::Application::Instance->getViewProvider(doc->getActiveObject());
MeshGui::ViewProviderMesh* vpmesh = dynamic_cast<MeshGui::ViewProviderMesh*>(vpm);
auto svp = Base::freecad_dynamic_cast<PartGui::ViewProviderPartExt>(
Gui::Application::Instance->getViewProvider(obj));
Gui::Application::Instance->getViewProvider(obj));
if (vpmesh && svp) {
std::vector<App::Color> diff_col = svp->DiffuseColor.getValues();
if (ui->groupsFaceColors->isChecked()) {
@@ -374,12 +392,14 @@ std::vector<App::Color> Tessellation::getUniqueColors(const std::vector<App::Col
{
// unique colors
std::set<uint32_t> col_set;
for (const auto& it : colors)
for (const auto& it : colors) {
col_set.insert(it.getPackedValue());
}
std::vector<App::Color> unique;
for (const auto& it : col_set)
for (const auto& it : col_set) {
unique.emplace_back(it);
}
return unique;
}
@@ -411,14 +431,15 @@ QString Tessellation::getStandardParameters(App::DocumentObject* obj) const
"LinearDeflection=%1, "
"AngularDeflection=%2, "
"Relative=%3")
.arg(devFace)
.arg(devAngle)
.arg(relative ? QString::fromLatin1("True") : QString::fromLatin1("False"));
if (ui->meshShapeColors->isChecked())
.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<PartGui::ViewProviderPartExt>(
Gui::Application::Instance->getViewProvider(obj));
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,
@@ -431,7 +452,8 @@ QString Tessellation::getStandardParameters(App::DocumentObject* obj) const
//
// PartGui::ViewProviderPartExt::getShapeColors().
//
param += QString::fromLatin1(",GroupColors=Gui.getDocument('%1').getObject('%2').DiffuseColor")
param +=
QString::fromLatin1(",GroupColors=Gui.getDocument('%1').getObject('%2').DiffuseColor")
.arg(QString::fromLatin1(obj->getDocument()->getName()),
QString::fromLatin1(obj->getNameInDocument()));
}
@@ -442,8 +464,9 @@ QString Tessellation::getStandardParameters(App::DocumentObject* obj) const
QString Tessellation::getMefistoParameters() const
{
double maxEdge = ui->spinMaximumEdgeLength->value().getValue();
if (!ui->spinMaximumEdgeLength->isEnabled())
if (!ui->spinMaximumEdgeLength->isEnabled()) {
maxEdge = 0;
}
return QString::fromLatin1("Shape=__shape__,MaxLength=%1").arg(maxEdge);
}
@@ -459,21 +482,22 @@ QString Tessellation::getNetgenParameters() const
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);
"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);
"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;
@@ -481,7 +505,8 @@ QString Tessellation::getNetgenParameters() const
// ---------------------------------------
class Mesh2ShapeGmsh::Private {
class Mesh2ShapeGmsh::Private
{
public:
std::string label;
std::list<App::SubObjectT> shapes;
@@ -492,8 +517,8 @@ public:
};
Mesh2ShapeGmsh::Mesh2ShapeGmsh(QWidget* parent, Qt::WindowFlags fl)
: GmshWidget(parent, fl)
, d(new Private())
: GmshWidget(parent, fl)
, d(new Private())
{
d->cadFile = App::Application::getTempFileName() + "mesh.brep";
d->stlFile = App::Application::getTempFileName() + "mesh.stl";
@@ -526,40 +551,46 @@ bool Mesh2ShapeGmsh::writeProject(QString& inpFile, QString& outFile)
// Parameters
int algorithm = meshingAlgorithm();
double maxSize = getMaxSize();
if (maxSize == 0.0)
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"
<< "// High-order meshes optimization (0=none, 1=optimization, 2=elastic+optimization, 3=elastic, 4=fast curving)\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, 9=Packing of Parallelograms)\n"
<< "Mesh.Algorithm = " << algorithm << ";\n"
<< "// 3D mesh algorithm (1=Delaunay, 2=New Delaunay, 4=Frontal, 7=MMG3D, 9=R-tree, 10=HTX)\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";
<< "// 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"
<< "// High-order meshes optimization (0=none, 1=optimization, "
"2=elastic+optimization, 3=elastic, 4=fast curving)\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, 9=Packing of Parallelograms)\n"
<< "Mesh.Algorithm = " << algorithm << ";\n"
<< "// 3D mesh algorithm (1=Delaunay, 2=New Delaunay, 4=Frontal, 7=MMG3D, "
"9=R-tree, 10=HTX)\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());
@@ -570,8 +601,9 @@ bool Mesh2ShapeGmsh::writeProject(QString& inpFile, QString& outFile)
}
else {
App::Document* doc = d->doc.getDocument();
if (doc)
if (doc) {
doc->commitTransaction();
}
Q_EMIT processed();
}
@@ -582,8 +614,9 @@ bool Mesh2ShapeGmsh::writeProject(QString& inpFile, QString& outFile)
bool Mesh2ShapeGmsh::loadOutput()
{
App::Document* doc = d->doc.getDocument();
if (!doc)
if (!doc) {
return false;
}
// Now read-in the mesh
Base::FileInfo stl(d->stlFile);
@@ -613,20 +646,20 @@ bool Mesh2ShapeGmsh::loadOutput()
TaskTessellation::TaskTessellation()
{
widget = new Tessellation();
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
QPixmap()/*Gui::BitmapFactory().pixmap("MeshPart_Mesher")*/,
widget->windowTitle(), true, nullptr);
Gui::TaskView::TaskBox* taskbox =
new Gui::TaskView::TaskBox(QPixmap() /*Gui::BitmapFactory().pixmap("MeshPart_Mesher")*/,
widget->windowTitle(),
true,
nullptr);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
void TaskTessellation::open()
{
}
{}
void TaskTessellation::clicked(int)
{
}
{}
bool TaskTessellation::accept()
{

View File

@@ -23,25 +23,27 @@
#ifndef MESHPARTGUI_TESSELLATION_H
#define MESHPARTGUI_TESSELLATION_H
#include <memory>
#include <QPointer>
#include <memory>
#include <Gui/TaskView/TaskDialog.h>
#include <Gui/TaskView/TaskView.h>
#include <Mod/Mesh/Gui/RemeshGmsh.h>
namespace App {
namespace App
{
class Document;
class SubObjectT;
}
namespace MeshPartGui {
}// namespace App
namespace MeshPartGui
{
/**
* Non-modal dialog to mesh a shape.
* @author Werner Mayer
*/
class Mesh2ShapeGmsh : public MeshGui::GmshWidget
class Mesh2ShapeGmsh: public MeshGui::GmshWidget
{
Q_OBJECT
@@ -64,18 +66,20 @@ private:
};
class Ui_Tessellation;
class Tessellation : public QWidget
class Tessellation: public QWidget
{
Q_OBJECT
enum {
enum
{
Standard,
Mefisto,
Netgen,
Gmsh
};
enum {
enum
{
VeryCoarse = 0,
Coarse = 1,
Moderate = 2,
@@ -89,7 +93,7 @@ public:
bool accept();
protected:
void changeEvent(QEvent *e) override;
void changeEvent(QEvent* e) override;
void process(int method, App::Document* doc, const std::list<App::SubObjectT>&);
void saveParameters(int method);
void setFaceColors(int method, App::Document* doc, App::DocumentObject* obj);
@@ -114,7 +118,7 @@ private:
std::unique_ptr<Ui_Tessellation> ui;
};
class TaskTessellation : public Gui::TaskView::TaskDialog
class TaskTessellation: public Gui::TaskView::TaskDialog
{
Q_OBJECT
@@ -128,12 +132,14 @@ public:
bool reject() override;
QDialogButtonBox::StandardButtons getStandardButtons() const override
{ return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; }
{
return QDialogButtonBox::Ok | QDialogButtonBox::Cancel;
}
private:
Tessellation* widget;
};
} // namespace MeshPartGui
}// namespace MeshPartGui
#endif // MESHPARTGUI_TESSELLATION_H
#endif// MESHPARTGUI_TESSELLATION_H

View File

@@ -22,7 +22,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <qobject.h>
#include <qobject.h>
#endif
#include <Gui/ToolBarManager.h>
@@ -32,7 +32,7 @@
using namespace MeshPartGui;
#if 0 // needed for Qt's lupdate utility
#if 0// needed for Qt's lupdate utility
qApp->translate("Workbench", "MeshPart");
#endif
@@ -49,7 +49,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
Gui::ToolBarItem* part = new Gui::ToolBarItem(root);
part->setCommand("MeshPart");
*part << "MeshPart_Mesher";
return root;
return root;
}
Gui::ToolBarItem* Workbench::setupCommandBars() const
@@ -58,4 +58,3 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
Gui::ToolBarItem* root = new Gui::ToolBarItem;
return root;
}

View File

@@ -26,25 +26,26 @@
#include <Gui/Workbench.h>
namespace MeshPartGui {
namespace MeshPartGui
{
/**
* @author Werner Mayer
*/
class Workbench : public Gui::StdWorkbench
class Workbench: public Gui::StdWorkbench
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
Workbench();
~Workbench() override;
Workbench();
~Workbench() override;
protected:
Gui::ToolBarItem* setupToolBars() const override;
Gui::ToolBarItem* setupCommandBars() const override;
Gui::ToolBarItem* setupToolBars() const override;
Gui::ToolBarItem* setupCommandBars() const override;
};
} // namespace MeshPartGui
}// namespace MeshPartGui
#endif // MESHPARTGUI_WORKBENCH_H
#endif// MESHPARTGUI_WORKBENCH_H