diff --git a/src/Mod/MeshPart/App/AppMeshPartPy.cpp b/src/Mod/MeshPart/App/AppMeshPartPy.cpp index 1a9387f40..c32c5e1c9 100644 --- a/src/Mod/MeshPart/App/AppMeshPartPy.cpp +++ b/src/Mod/MeshPart/App/AppMeshPartPy.cpp @@ -177,6 +177,20 @@ private: { PyObject *shape; + static char* kwds_lindeflection[] = {"Shape", "LinearDeflection", "AngularDeflection", NULL}; + PyErr_Clear(); + double lindeflection=0; + double angdeflection=0.5; + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!d|d", kwds_lindeflection, + &(Part::TopoShapePy::Type), &shape, &lindeflection, &angdeflection)) { + MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->getShape()); + mesher.setMethod(MeshPart::Mesher::Standard); + mesher.setDeflection(lindeflection); + mesher.setAngularDeflection(angdeflection); + mesher.setRegular(true); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); + } + static char* kwds_maxLength[] = {"Shape", "MaxLength",NULL}; PyErr_Clear(); double maxLength=0; diff --git a/src/Mod/MeshPart/App/Mesher.cpp b/src/Mod/MeshPart/App/Mesher.cpp index 68a508785..6737f90b6 100644 --- a/src/Mod/MeshPart/App/Mesher.cpp +++ b/src/Mod/MeshPart/App/Mesher.cpp @@ -21,13 +21,21 @@ ***************************************************************************/ #include "PreCompiled.h" +#include #include "Mesher.h" #include #include +#include #include #include +#include +#include +#include +#include +#include +#include #ifdef HAVE_SMESH #include @@ -88,6 +96,43 @@ int MeshingOutput::sync() return 0; } +// ---------------------------------------------------------------------------- + +struct Mesher::Vertex { + static const double deflection; + Standard_Real x,y,z; + Standard_Integer i; + mutable MeshCore::MeshPoint p; + + Vertex(Standard_Real X, Standard_Real Y, Standard_Real Z) + : x(X),y(Y),z(Z),i(0) + { + p.x = static_cast(x); + p.y = static_cast(y); + p.z = static_cast(z); + } + + const MeshCore::MeshPoint& toPoint() const + { + return p; + } + + bool operator < (const Vertex &v) const + { + if (fabs ( this->x - v.x) >= deflection) + return this->x < v.x; + if (fabs ( this->y - v.y) >= deflection) + return this->y < v.y; + if (fabs ( this->z - v.z) >= deflection) + return this->z < v.z; + return false; // points are considered to be equal + } +}; + +const double Mesher::Vertex::deflection = gp::Resolution(); + +// ---------------------------------------------------------------------------- + Mesher::Mesher(const TopoDS_Shape& s) : shape(s) , method(None) @@ -95,6 +140,7 @@ Mesher::Mesher(const TopoDS_Shape& s) , maxArea(0) , localLength(0) , deflection(0) + , angularDeflection(0.5) , minLen(0) , maxLen(0) , regular(false) @@ -116,6 +162,110 @@ Mesher::~Mesher() Mesh::MeshObject* Mesher::createMesh() const { + // OCC standard mesher + if (method == Standard) { + Handle_StlMesh_Mesh aMesh = new StlMesh_Mesh(); + + if (!shape.IsNull()) { + BRepTools::Clean(shape); +#if OCC_VERSION_HEX >= 0x060801 + BRepMesh_IncrementalMesh bMesh(shape, deflection, Standard_False, angularDeflection); + StlTransfer::RetrieveMesh(shape,aMesh); +#else + StlTransfer::BuildIncrementalMesh(shape, deflection, +#if OCC_VERSION_HEX >= 0x060503 + Standard_True, +#endif + aMesh); +#endif + } + + MeshCore::MeshFacetArray faces; + faces.reserve(aMesh->NbTriangles()); + + std::set vertices; + Standard_Real x1, y1, z1; + Standard_Real x2, y2, z2; + Standard_Real x3, y3, z3; + + std::list< std::vector > meshSegments; + std::size_t numMeshFaces = 0; + StlMesh_MeshExplorer xp(aMesh); + for (Standard_Integer nbd=1;nbd<=aMesh->NbDomains();nbd++) { + std::size_t numDomainFaces = 0; + for (xp.InitTriangle(nbd); xp.MoreTriangle(); xp.NextTriangle()) { + xp.TriangleVertices(x1,y1,z1,x2,y2,z2,x3,y3,z3); + std::set::iterator it; + MeshCore::MeshFacet face; + + // 1st vertex + Vertex v1(x1,y1,z1); + it = vertices.find(v1); + if (it == vertices.end()) { + v1.i = vertices.size(); + face._aulPoints[0] = v1.i; + vertices.insert(v1); + } + else { + face._aulPoints[0] = it->i; + } + + // 2nd vertex + Vertex v2(x2,y2,z2); + it = vertices.find(v2); + if (it == vertices.end()) { + v2.i = vertices.size(); + face._aulPoints[1] = v2.i; + vertices.insert(v2); + } + else { + face._aulPoints[1] = it->i; + } + + // 3rd vertex + Vertex v3(x3,y3,z3); + it = vertices.find(v3); + if (it == vertices.end()) { + v3.i = vertices.size(); + face._aulPoints[2] = v3.i; + vertices.insert(v3); + } + else { + face._aulPoints[2] = it->i; + } + + // make sure that we don't insert invalid facets + if (face._aulPoints[0] != face._aulPoints[1] && + face._aulPoints[1] != face._aulPoints[2] && + face._aulPoints[2] != face._aulPoints[0]) { + faces.push_back(face); + numDomainFaces++; + } + } + + // add a segment for the face + std::vector segment(numDomainFaces); + std::generate(segment.begin(), segment.end(), Base::iotaGen(numMeshFaces)); + numMeshFaces += numDomainFaces; + meshSegments.push_back(segment); + } + + MeshCore::MeshPointArray verts; + verts.resize(vertices.size()); + for (auto it : vertices) + verts[it.i] = it.toPoint(); + + MeshCore::MeshKernel kernel; + kernel.Adopt(verts, faces, true); + + Mesh::MeshObject* meshdata = new Mesh::MeshObject(); + meshdata->swap(kernel); + for (auto it : meshSegments) { + meshdata->addSegment(it); + } + return meshdata; + } + #ifndef HAVE_SMESH throw Base::Exception("SMESH is not available on this platform"); #else diff --git a/src/Mod/MeshPart/App/Mesher.h b/src/Mod/MeshPart/App/Mesher.h index 5b1a8d119..f9bcfc750 100644 --- a/src/Mod/MeshPart/App/Mesher.h +++ b/src/Mod/MeshPart/App/Mesher.h @@ -40,6 +40,7 @@ public: #if defined (HAVE_NETGEN) Netgen = 2, #endif + Standard = 3 }; Mesher(const TopoDS_Shape&); @@ -68,6 +69,10 @@ public: { deflection = s; } double getDeflection() const { return deflection; } + void setAngularDeflection(double s) + { angularDeflection = s; } + double getAngularDeflection() const + { return angularDeflection; } void setMinMaxLengths(double f, double l) { minLen = f; maxLen = l; } void getMinMaxLengths(double& f, double& l) const @@ -121,6 +126,7 @@ private: double maxArea; double localLength; double deflection; + double angularDeflection; double minLen, maxLen; bool regular; #if defined (HAVE_NETGEN) @@ -132,6 +138,7 @@ private: bool optimize; bool allowquad; #endif + struct Vertex; }; class MeshingOutput : public std::streambuf diff --git a/src/Mod/MeshPart/Gui/Tessellation.cpp b/src/Mod/MeshPart/Gui/Tessellation.cpp index a579861a8..ddbb4c822 100644 --- a/src/Mod/MeshPart/Gui/Tessellation.cpp +++ b/src/Mod/MeshPart/Gui/Tessellation.cpp @@ -249,7 +249,7 @@ bool Tessellation::accept() cmd = QString::fromLatin1( "__doc__=FreeCAD.getDocument(\"%1\")\n" "__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n" - "__mesh__.Mesh=Mesh.Mesh(__doc__.getObject(\"%2\").Shape.tessellate(%3))\n" + "__mesh__.Mesh=MeshPart.meshFromShape(Shape=__doc__.getObject(\"%2\").Shape,LinearDeflection=%3)\n" "__mesh__.Label=\"%4 (Meshed)\"\n" "__mesh__.ViewObject.CreaseAngle=25.0\n" "del __doc__, __mesh__\n")