Skip to content

Commit

Permalink
+ Advanced options for different meshing algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Nov 7, 2013
1 parent e28f387 commit c57ab85
Show file tree
Hide file tree
Showing 7 changed files with 665 additions and 167 deletions.
117 changes: 99 additions & 18 deletions src/Mod/MeshPart/App/AppMeshPartPy.cpp
Expand Up @@ -135,38 +135,119 @@ 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 */
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 */
};
92 changes: 63 additions & 29 deletions src/Mod/MeshPart/App/Mesher.cpp
Expand Up @@ -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)
{
}

Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
42 changes: 42 additions & 0 deletions src/Mod/MeshPart/App/Mesher.h
Expand Up @@ -37,6 +37,8 @@ class Mesher
Mesher(const TopoDS_Shape&);
~Mesher();

/** @name Mefisto settings */
//@{
void setMaxLength(double s)
{ maxLength = s; }
double getMaxLength() const
Expand All @@ -61,6 +63,39 @@ class Mesher
{ 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;

Expand All @@ -72,6 +107,13 @@ class Mesher
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
Expand Down
4 changes: 4 additions & 0 deletions src/Mod/MeshPart/Gui/CMakeLists.txt
Expand Up @@ -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}
Expand Down

0 comments on commit c57ab85

Please sign in to comment.