+ Advanced options for different meshing algorithms
This commit is contained in:
@@ -135,30 +135,111 @@ wireFromSegment(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
meshFromShape(PyObject *self, PyObject *args)
|
||||
meshFromShape(PyObject *self, PyObject *args, PyObject* kwds)
|
||||
{
|
||||
PyObject *shape;
|
||||
float maxLength=1.0f/*0.5f*/;
|
||||
float maxArea=0/*1.0f*/;
|
||||
float localLen=0/*0.1f*/;
|
||||
float deflection=0/*0.01f*/;
|
||||
if (!PyArg_ParseTuple(args, "O!|ffff", &(Part::TopoShapePy::Type), &shape,
|
||||
&maxLength,&maxArea,&localLen,&deflection))
|
||||
return 0;
|
||||
|
||||
try {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setMaxLength(maxLength);
|
||||
mesher.setMaxArea(maxArea);
|
||||
mesher.setLocalLength(localLen);
|
||||
mesher.setDeflection(deflection);
|
||||
mesher.setRegular(true);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
PyObject *shape;
|
||||
|
||||
static char* kwds_maxLength[] = {"Shape", "MaxLength",NULL};
|
||||
PyErr_Clear();
|
||||
double maxLength=0;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_maxLength,
|
||||
&(Part::TopoShapePy::Type), &shape, &maxLength)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setMaxLength(maxLength);
|
||||
mesher.setRegular(true);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
|
||||
static char* kwds_maxArea[] = {"Shape", "MaxArea",NULL};
|
||||
PyErr_Clear();
|
||||
double maxArea=0;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_maxArea,
|
||||
&(Part::TopoShapePy::Type), &shape, &maxArea)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setMaxArea(maxArea);
|
||||
mesher.setRegular(true);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
|
||||
static char* kwds_localLen[] = {"Shape", "LocalLength",NULL};
|
||||
PyErr_Clear();
|
||||
double localLen=0;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_localLen,
|
||||
&(Part::TopoShapePy::Type), &shape, &localLen)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setLocalLength(localLen);
|
||||
mesher.setRegular(true);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
|
||||
static char* kwds_deflection[] = {"Shape", "Deflection",NULL};
|
||||
PyErr_Clear();
|
||||
double deflection=0;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_deflection,
|
||||
&(Part::TopoShapePy::Type), &shape, &deflection)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setDeflection(deflection);
|
||||
mesher.setRegular(true);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
|
||||
static char* kwds_minmaxLen[] = {"Shape", "MinLength","MaxLength",NULL};
|
||||
PyErr_Clear();
|
||||
double minLen=0, maxLen=0;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!dd", kwds_minmaxLen,
|
||||
&(Part::TopoShapePy::Type), &shape, &minLen, &maxLen)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setMinMaxLengths(minLen, maxLen);
|
||||
mesher.setRegular(true);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
|
||||
static char* kwds_fineness[] = {"Shape", "Fineness", "SecondOrder", "Optimize", "AllowQuad",NULL};
|
||||
PyErr_Clear();
|
||||
int fineness=0, secondOrder=0, optimize=1, allowquad=0;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!i|iii", kwds_fineness,
|
||||
&(Part::TopoShapePy::Type), &shape, &fineness,
|
||||
&secondOrder, &optimize, &allowquad)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setFineness(fineness);
|
||||
mesher.setSecondOrder(secondOrder > 0);
|
||||
mesher.setOptimize(optimize > 0);
|
||||
mesher.setQuadAllowed(allowquad > 0);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
|
||||
static char* kwds_user[] = {"Shape", "GrowthRate", "SegPerEdge", "SegPerRadius", "SecondOrder", "Optimize", "AllowQuad",NULL};
|
||||
PyErr_Clear();
|
||||
double growthRate=0, nbSegPerEdge=0, nbSegPerRadius=0;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O!|dddiii", kwds_user,
|
||||
&(Part::TopoShapePy::Type), &shape,
|
||||
&growthRate, &nbSegPerEdge, &nbSegPerRadius,
|
||||
&secondOrder, &optimize, &allowquad)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setGrowthRate(growthRate);
|
||||
mesher.setNbSegPerEdge(nbSegPerEdge);
|
||||
mesher.setNbSegPerRadius(nbSegPerRadius);
|
||||
mesher.setSecondOrder(secondOrder > 0);
|
||||
mesher.setOptimize(optimize > 0);
|
||||
mesher.setQuadAllowed(allowquad > 0);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
if (PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &shape)) {
|
||||
MeshPart::Mesher mesher(static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->_Shape);
|
||||
mesher.setRegular(true);
|
||||
return new Mesh::MeshPy(mesher.createMesh());
|
||||
}
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
PyErr_SetString(PyExc_Exception, e.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_Exception,"Wrong arguments");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* registration table */
|
||||
@@ -166,7 +247,7 @@ struct PyMethodDef MeshPart_methods[] = {
|
||||
{"loftOnCurve",loftOnCurve, METH_VARARGS, loft_doc},
|
||||
{"wireFromSegment",wireFromSegment, METH_VARARGS,
|
||||
"Create wire(s) from boundary of segment"},
|
||||
{"meshFromShape",meshFromShape, METH_VARARGS,
|
||||
{"meshFromShape",(PyCFunction)meshFromShape, METH_VARARGS|METH_KEYWORDS,
|
||||
"Create mesh from shape"},
|
||||
{NULL, NULL} /* end of table marker */
|
||||
};
|
||||
|
||||
@@ -90,7 +90,9 @@ int MeshingOutput::sync()
|
||||
|
||||
Mesher::Mesher(const TopoDS_Shape& s)
|
||||
: shape(s), maxLength(0), maxArea(0), localLength(0),
|
||||
deflection(0), minLen(0), maxLen(0), regular(false)
|
||||
deflection(0), minLen(0), maxLen(0), regular(false),
|
||||
fineness(5), growthRate(0), nbSegPerEdge(0), nbSegPerRadius(0),
|
||||
secondOrder(false), optimize(true), allowquad(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -112,37 +114,22 @@ Mesh::MeshObject* Mesher::createMesh() const
|
||||
#if defined(_MSC_VER)
|
||||
NETGENPlugin_Hypothesis_2D* hyp2d = new NETGENPlugin_Hypothesis_2D(hyp++,0,meshgen);
|
||||
|
||||
//TODO: Try to find values so that we get similar results as with Mefisto meshing
|
||||
double growth = 0;
|
||||
if (maxLength > 0 && localLength > 0) {
|
||||
growth = std::min<double>(maxLength, localLength);
|
||||
if (fineness >=0 && fineness < 5) {
|
||||
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::Fineness(fineness));
|
||||
}
|
||||
else if (maxLength > 0) {
|
||||
growth = maxLength;
|
||||
}
|
||||
else if (localLength > 0) {
|
||||
growth = localLength;
|
||||
// user defined values
|
||||
else {
|
||||
if (growthRate > 0)
|
||||
hyp2d->SetGrowthRate(growthRate);
|
||||
if (nbSegPerEdge > 0)
|
||||
hyp2d->SetNbSegPerEdge(nbSegPerEdge);
|
||||
if (nbSegPerRadius > 0)
|
||||
hyp2d->SetNbSegPerRadius(nbSegPerRadius);
|
||||
}
|
||||
|
||||
if (growth == 0.0)
|
||||
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::Moderate);
|
||||
else if (growth <= 0.1)
|
||||
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::VeryFine);
|
||||
else if (growth <= 0.2f)
|
||||
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::Fine);
|
||||
else if (growth <= 0.5f)
|
||||
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::Moderate);
|
||||
else if (growth <= 0.7f)
|
||||
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::Coarse);
|
||||
else
|
||||
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::VeryCoarse);
|
||||
|
||||
//hyp2d->SetGrowthRate(growth);
|
||||
//hyp2d->SetNbSegPerEdge(5);
|
||||
//hyp2d->SetNbSegPerRadius(10);
|
||||
hyp2d->SetQuadAllowed(false);
|
||||
hyp2d->SetOptimize(true);
|
||||
hyp2d->SetSecondOrder(true); // apply bisecting to create four triangles out of one
|
||||
hyp2d->SetQuadAllowed(allowquad);
|
||||
hyp2d->SetOptimize(optimize);
|
||||
hyp2d->SetSecondOrder(secondOrder); // apply bisecting to create four triangles out of one
|
||||
hypoth.push_back(hyp2d);
|
||||
|
||||
NETGENPlugin_NETGEN_2D* alg2d = new NETGENPlugin_NETGEN_2D(hyp++,0,meshgen);
|
||||
@@ -285,6 +272,53 @@ Mesh::MeshObject* Mesher::createMesh() const
|
||||
faces.push_back(f3);
|
||||
faces.push_back(f4);
|
||||
}
|
||||
#if 0 // FIXME: how does the structure look like?
|
||||
else if (aFace->NbNodes() == 8) {
|
||||
MeshCore::MeshFacet f1, f2, f3, f4, f5, f6;
|
||||
const SMDS_MeshNode* node0 = aFace->GetNode(0);
|
||||
const SMDS_MeshNode* node1 = aFace->GetNode(1);
|
||||
const SMDS_MeshNode* node2 = aFace->GetNode(2);
|
||||
const SMDS_MeshNode* node3 = aFace->GetNode(3);
|
||||
const SMDS_MeshNode* node4 = aFace->GetNode(4);
|
||||
const SMDS_MeshNode* node5 = aFace->GetNode(5);
|
||||
const SMDS_MeshNode* node6 = aFace->GetNode(5);
|
||||
const SMDS_MeshNode* node7 = aFace->GetNode(5);
|
||||
|
||||
f1._aulPoints[0] = mapNodeIndex[node0];
|
||||
f1._aulPoints[1] = mapNodeIndex[node4];
|
||||
f1._aulPoints[2] = mapNodeIndex[node7];
|
||||
|
||||
f2._aulPoints[0] = mapNodeIndex[node1];
|
||||
f2._aulPoints[1] = mapNodeIndex[node5];
|
||||
f2._aulPoints[2] = mapNodeIndex[node4];
|
||||
|
||||
f3._aulPoints[0] = mapNodeIndex[node2];
|
||||
f3._aulPoints[1] = mapNodeIndex[node6];
|
||||
f3._aulPoints[2] = mapNodeIndex[node5];
|
||||
|
||||
f4._aulPoints[0] = mapNodeIndex[node3];
|
||||
f4._aulPoints[1] = mapNodeIndex[node7];
|
||||
f4._aulPoints[2] = mapNodeIndex[node6];
|
||||
|
||||
f5._aulPoints[0] = mapNodeIndex[node4];
|
||||
f5._aulPoints[1] = mapNodeIndex[node6];
|
||||
f5._aulPoints[2] = mapNodeIndex[node7];
|
||||
|
||||
f6._aulPoints[0] = mapNodeIndex[node4];
|
||||
f6._aulPoints[1] = mapNodeIndex[node5];
|
||||
f6._aulPoints[2] = mapNodeIndex[node6];
|
||||
|
||||
faces.push_back(f1);
|
||||
faces.push_back(f2);
|
||||
faces.push_back(f3);
|
||||
faces.push_back(f4);
|
||||
faces.push_back(f5);
|
||||
faces.push_back(f6);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
Base::Console().Warning("Face with %d nodes ignored\n", aFace->NbNodes());
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
Mesher(const TopoDS_Shape&);
|
||||
~Mesher();
|
||||
|
||||
/** @name Mefisto settings */
|
||||
//@{
|
||||
void setMaxLength(double s)
|
||||
{ maxLength = s; }
|
||||
double getMaxLength() const
|
||||
@@ -61,6 +63,39 @@ public:
|
||||
{ regular = s; }
|
||||
bool isRegular() const
|
||||
{ return regular; }
|
||||
//@}
|
||||
|
||||
/** @name Netgen settings */
|
||||
//@{
|
||||
void setFineness(int s)
|
||||
{ fineness = s; }
|
||||
int getFineness() const
|
||||
{ return fineness; }
|
||||
void setGrowthRate(double r)
|
||||
{ growthRate = r; }
|
||||
double getGrowthRate() const
|
||||
{ return growthRate; }
|
||||
void setNbSegPerEdge(double v)
|
||||
{ nbSegPerEdge = v;}
|
||||
double getNbSegPerEdge() const
|
||||
{ return nbSegPerEdge; }
|
||||
void setNbSegPerRadius(double v)
|
||||
{ nbSegPerRadius = v; }
|
||||
double getNbSegPerRadius() const
|
||||
{ return nbSegPerRadius; }
|
||||
void setSecondOrder(bool on)
|
||||
{ secondOrder = on; }
|
||||
bool getSecondOrder() const
|
||||
{ return secondOrder; }
|
||||
void setOptimize(bool on)
|
||||
{ optimize = on;}
|
||||
bool getOptimize() const
|
||||
{ return optimize; }
|
||||
void setQuadAllowed(bool on)
|
||||
{ allowquad = on;}
|
||||
bool isQuadAllowed() const
|
||||
{ return allowquad; }
|
||||
//@}
|
||||
|
||||
Mesh::MeshObject* createMesh() const;
|
||||
|
||||
@@ -72,6 +107,13 @@ private:
|
||||
double deflection;
|
||||
double minLen, maxLen;
|
||||
bool regular;
|
||||
int fineness;
|
||||
double growthRate;
|
||||
double nbSegPerEdge;
|
||||
double nbSegPerRadius;
|
||||
bool secondOrder;
|
||||
bool optimize;
|
||||
bool allowquad;
|
||||
};
|
||||
|
||||
class MeshingOutput : public std::streambuf
|
||||
|
||||
@@ -4,6 +4,10 @@ else(MSVC)
|
||||
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
|
||||
endif(MSVC)
|
||||
|
||||
if(FREECAD_BUILD_FEM_NETGEN)
|
||||
add_definitions(-DHAVE_NETGEN)
|
||||
endif(FREECAD_BUILD_FEM_NETGEN)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
|
||||
@@ -49,6 +49,31 @@ Tessellation::Tessellation(QWidget* parent)
|
||||
: QWidget(parent), ui(new Ui_Tessellation)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
buttonGroup = new QButtonGroup(this);
|
||||
buttonGroup->addButton(ui->radioButtonStandard, 0);
|
||||
buttonGroup->addButton(ui->radioButtonMefisto, 1);
|
||||
buttonGroup->addButton(ui->radioButtonNetgen, 2);
|
||||
connect(buttonGroup, SIGNAL(buttonClicked(int)),
|
||||
this, SLOT(meshingMethod(int)));
|
||||
|
||||
// set the standard method
|
||||
ui->radioButtonStandard->setChecked(true);
|
||||
ui->comboFineness->setCurrentIndex(2);
|
||||
on_comboFineness_currentIndexChanged(2);
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
ui->radioButtonMefisto->setDisabled(true);
|
||||
#else
|
||||
ui->radioButtonMefisto->setChecked(true);
|
||||
#endif
|
||||
#if !defined (HAVE_NETGEN)
|
||||
ui->radioButtonNetgen->setDisabled(true);
|
||||
#else
|
||||
ui->radioButtonNetgen->setChecked(true);
|
||||
#endif
|
||||
meshingMethod(buttonGroup->checkedId());
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc, "import Mesh, MeshPart");
|
||||
findShapes();
|
||||
}
|
||||
@@ -57,24 +82,73 @@ Tessellation::~Tessellation()
|
||||
{
|
||||
}
|
||||
|
||||
void Tessellation::on_checkSimpleMethod_toggled(bool on)
|
||||
void Tessellation::meshingMethod(int id)
|
||||
{
|
||||
if (!on) {
|
||||
if (ui->checkMaxEdgeLength->isChecked()) {
|
||||
ui->checkMaxEdgeLength->setEnabled(true);
|
||||
ui->spinMaxEdgeLength->setEnabled(true);
|
||||
}
|
||||
ui->stackedWidget->setCurrentIndex(id);
|
||||
}
|
||||
|
||||
void Tessellation::on_comboFineness_currentIndexChanged(int index)
|
||||
{
|
||||
if (index == 5) {
|
||||
ui->doubleGrading->setEnabled(true);
|
||||
ui->spinEdgeElements->setEnabled(true);
|
||||
ui->spinCurvatureElements->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui->checkMaxEdgeLength->setEnabled(false);
|
||||
ui->spinMaxEdgeLength->setEnabled(false);
|
||||
ui->doubleGrading->setEnabled(false);
|
||||
ui->spinEdgeElements->setEnabled(false);
|
||||
ui->spinCurvatureElements->setEnabled(false);
|
||||
}
|
||||
|
||||
switch (index) {
|
||||
case 0: // Very coarse
|
||||
ui->doubleGrading->setValue(0.7);
|
||||
ui->spinEdgeElements->setValue(0.3);
|
||||
ui->spinCurvatureElements->setValue(1.0);
|
||||
break;
|
||||
case 1: // Coarse
|
||||
ui->doubleGrading->setValue(0.5);
|
||||
ui->spinEdgeElements->setValue(0.5);
|
||||
ui->spinCurvatureElements->setValue(1.5);
|
||||
break;
|
||||
case 2: // Moderate
|
||||
ui->doubleGrading->setValue(0.3);
|
||||
ui->spinEdgeElements->setValue(1.0);
|
||||
ui->spinCurvatureElements->setValue(2.0);
|
||||
break;
|
||||
case 3: // Fine
|
||||
ui->doubleGrading->setValue(0.2);
|
||||
ui->spinEdgeElements->setValue(2.0);
|
||||
ui->spinCurvatureElements->setValue(3.0);
|
||||
break;
|
||||
case 4: // Very fine
|
||||
ui->doubleGrading->setValue(0.1);
|
||||
ui->spinEdgeElements->setValue(3.0);
|
||||
ui->spinCurvatureElements->setValue(5.0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Tessellation::on_checkSecondOrder_toggled(bool on)
|
||||
{
|
||||
if (on)
|
||||
ui->checkQuadDominated->setChecked(false);
|
||||
}
|
||||
|
||||
void Tessellation::on_checkQuadDominated_toggled(bool on)
|
||||
{
|
||||
if (on)
|
||||
ui->checkSecondOrder->setChecked(false);
|
||||
}
|
||||
|
||||
void Tessellation::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
int index = ui->comboFineness->currentIndex();
|
||||
ui->retranslateUi(this);
|
||||
ui->comboFineness->setCurrentIndex(index);
|
||||
}
|
||||
QWidget::changeEvent(e);
|
||||
}
|
||||
@@ -123,7 +197,7 @@ void Tessellation::findShapes()
|
||||
}
|
||||
}
|
||||
|
||||
ui->spinMaxEdgeLength->setValue(edgeLen/10);
|
||||
ui->spinMaximumEdgeLength->setValue(edgeLen/10);
|
||||
if (foundSelection)
|
||||
ui->treeWidget->hide();
|
||||
}
|
||||
@@ -147,17 +221,7 @@ bool Tessellation::accept()
|
||||
QString shape, label;
|
||||
Gui::WaitCursor wc;
|
||||
|
||||
bool simple = ui->checkSimpleMethod->isChecked();
|
||||
double devFace = ui->spinDeviation->value();
|
||||
if (!ui->spinDeviation->isEnabled()) {
|
||||
if (simple)
|
||||
devFace = 0.1;
|
||||
else
|
||||
devFace = 0;
|
||||
}
|
||||
double maxEdge = ui->spinMaxEdgeLength->value();
|
||||
if (!ui->spinMaxEdgeLength->isEnabled())
|
||||
maxEdge = 0;
|
||||
int method = buttonGroup->checkedId();
|
||||
|
||||
activeDoc->openTransaction("Meshing");
|
||||
QList<QTreeWidgetItem *> items = ui->treeWidget->selectedItems();
|
||||
@@ -167,32 +231,81 @@ bool Tessellation::accept()
|
||||
label = (*it)->text(0);
|
||||
|
||||
QString cmd;
|
||||
if (simple) {
|
||||
if (method == 0) { // Standard
|
||||
double devFace = ui->spinSurfaceDeviation->value();
|
||||
cmd = QString::fromAscii(
|
||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
||||
"__mesh__.Mesh=Mesh.Mesh(__doc__.getObject(\"%2\").Shape.tessellate(%3))\n"
|
||||
"__mesh__.Label=\"%4 (Meshed)\"\n"
|
||||
"__mesh__.ViewObject.CreaseAngle=25.0\n"
|
||||
"del __doc__, __mesh__\n")
|
||||
.arg(this->document)
|
||||
.arg(shape)
|
||||
.arg(devFace)
|
||||
.arg(label);
|
||||
}
|
||||
else {
|
||||
else if (method == 1) { // Mefisto
|
||||
double maxEdge = ui->spinMaximumEdgeLength->value();
|
||||
if (!ui->spinMaximumEdgeLength->isEnabled())
|
||||
maxEdge = 0;
|
||||
cmd = QString::fromAscii(
|
||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
||||
"__mesh__.Mesh=MeshPart.meshFromShape(__doc__.getObject(\"%2\").Shape,%3,0,0,%4)\n"
|
||||
"__mesh__.Label=\"%5 (Meshed)\"\n"
|
||||
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__doc__.getObject(\"%2\").Shape,MaxLength=%3)\n"
|
||||
"__mesh__.Label=\"%4 (Meshed)\"\n"
|
||||
"__mesh__.ViewObject.CreaseAngle=25.0\n"
|
||||
"del __doc__, __mesh__\n")
|
||||
.arg(this->document)
|
||||
.arg(shape)
|
||||
.arg(maxEdge)
|
||||
.arg(devFace)
|
||||
.arg(label);
|
||||
}
|
||||
else if (method == 2) { // 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) {
|
||||
cmd = QString::fromAscii(
|
||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
||||
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__doc__.getObject(\"%2\").Shape,"
|
||||
"Fineness=%3,SecondOrder=%4,Optimize=%5,AllowQuad=%6)\n"
|
||||
"__mesh__.Label=\"%7 (Meshed)\"\n"
|
||||
"__mesh__.ViewObject.CreaseAngle=25.0\n"
|
||||
"del __doc__, __mesh__\n")
|
||||
.arg(this->document)
|
||||
.arg(shape)
|
||||
.arg(fineness)
|
||||
.arg(secondOrder ? 1 : 0)
|
||||
.arg(optimize ? 1 : 0)
|
||||
.arg(allowquad ? 1 : 0)
|
||||
.arg(label);
|
||||
}
|
||||
else {
|
||||
cmd = QString::fromAscii(
|
||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
||||
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__doc__.getObject(\"%2\").Shape,"
|
||||
"GrowthRate=%3,SegPerEdge=%4,SegPerRadius=%5,SecondOrder=%6,Optimize=%7,AllowQuad=%8)\n"
|
||||
"__mesh__.Label=\"%9 (Meshed)\"\n"
|
||||
"__mesh__.ViewObject.CreaseAngle=25.0\n"
|
||||
"del __doc__, __mesh__\n")
|
||||
.arg(this->document)
|
||||
.arg(shape)
|
||||
.arg(growthRate)
|
||||
.arg(nbSegPerEdge)
|
||||
.arg(nbSegPerRadius)
|
||||
.arg(secondOrder ? 1 : 0)
|
||||
.arg(optimize ? 1 : 0)
|
||||
.arg(allowquad ? 1 : 0)
|
||||
.arg(label);
|
||||
}
|
||||
}
|
||||
Gui::Command::doCommand(Gui::Command::Doc, (const char*)cmd.toAscii());
|
||||
}
|
||||
activeDoc->commitTransaction();
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#include <Gui/Selection.h>
|
||||
#include <memory>
|
||||
|
||||
class QButtonGroup;
|
||||
|
||||
namespace MeshPartGui {
|
||||
|
||||
class Ui_Tessellation;
|
||||
@@ -48,10 +50,14 @@ private:
|
||||
void findShapes();
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_checkSimpleMethod_toggled(bool);
|
||||
void meshingMethod(int id);
|
||||
void on_comboFineness_currentIndexChanged(int);
|
||||
void on_checkSecondOrder_toggled(bool);
|
||||
void on_checkQuadDominated_toggled(bool);
|
||||
|
||||
private:
|
||||
QString document;
|
||||
QButtonGroup* buttonGroup;
|
||||
std::auto_ptr<Ui_Tessellation> ui;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>329</width>
|
||||
<height>431</height>
|
||||
<width>363</width>
|
||||
<height>508</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tessellation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="selectionMode">
|
||||
@@ -27,73 +27,312 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="groupBoxMeshingOptions">
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
<string>Meshing options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkDeviation">
|
||||
<property name="text">
|
||||
<string>Surface deviation:</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinDeviation">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkSimpleMethod">
|
||||
<property name="text">
|
||||
<string>Use simplified mesh generation method</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkMaxEdgeLength">
|
||||
<property name="text">
|
||||
<string>Max. edge length:</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinMaxEdgeLength">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QRadioButton" name="radioButtonStandard">
|
||||
<property name="text">
|
||||
<string>Standard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QRadioButton" name="radioButtonMefisto">
|
||||
<property name="text">
|
||||
<string>Mefisto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QRadioButton" name="radioButtonNetgen">
|
||||
<property name="text">
|
||||
<string>Netgen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="pageStandard">
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelSurfaceDeviation">
|
||||
<property name="text">
|
||||
<string>Surface deviation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="spinSurfaceDeviation">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>189</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageMefisto">
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkMaximumEdgeLength">
|
||||
<property name="text">
|
||||
<string>Maximum edge length:</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="spinMaximumEdgeLength">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>189</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageNetgen">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelFineness">
|
||||
<property name="text">
|
||||
<string>Fineness:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboFineness">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Very coarse</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Coarse</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Moderate</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Fine</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Very fine</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>User defined</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelGrading">
|
||||
<property name="text">
|
||||
<string>Mesh size grading:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleGrading">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.300000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelEdgeElements">
|
||||
<property name="text">
|
||||
<string>Elements per edge:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinEdgeElements">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.200000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelCurvatureElements">
|
||||
<property name="text">
|
||||
<string>Elements per curvature radius:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinCurvatureElements">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.200000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>2.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkOptimizeSurface">
|
||||
<property name="text">
|
||||
<string>Optimize surface</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkSecondOrder">
|
||||
<property name="text">
|
||||
<string>Second order elements</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkQuadDominated">
|
||||
<property name="text">
|
||||
<string>Quad dominated</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>37</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -102,43 +341,22 @@
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>treeWidget</tabstop>
|
||||
<tabstop>checkDeviation</tabstop>
|
||||
<tabstop>spinDeviation</tabstop>
|
||||
<tabstop>checkSimpleMethod</tabstop>
|
||||
<tabstop>checkMaxEdgeLength</tabstop>
|
||||
<tabstop>spinMaxEdgeLength</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>checkDeviation</sender>
|
||||
<sender>checkMaximumEdgeLength</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>spinDeviation</receiver>
|
||||
<receiver>spinMaximumEdgeLength</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>104</x>
|
||||
<y>359</y>
|
||||
<x>81</x>
|
||||
<y>343</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>308</x>
|
||||
<y>360</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkMaxEdgeLength</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>spinMaxEdgeLength</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>112</x>
|
||||
<y>396</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>197</x>
|
||||
<y>399</y>
|
||||
<x>208</x>
|
||||
<y>350</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
|
||||
Reference in New Issue
Block a user