diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index c444d33adc..9bd9a1f3b8 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -761,6 +761,10 @@ bool MeshAlgorithm::FillupHole(const std::vector& boundary, MeshGeomFacet triangle; triangle = cTria.GetTriangle(rPoints, facet); + TriangulationVerifier* verifier = cTria.GetVerifier(); + if (!verifier) + return true; + // Now we have two adjacent triangles which we check for overlaps. // Therefore we build a separation plane that must separate the two diametrically opposed points. Base::Vector3f planeNormal = rTriangle.GetNormal() % (rTriangle._aclPoints[(ref_side+1)%3]-rTriangle._aclPoints[ref_side]); @@ -768,9 +772,7 @@ bool MeshAlgorithm::FillupHole(const std::vector& boundary, Base::Vector3f ref_point = rTriangle._aclPoints[(ref_side+2)%3]; Base::Vector3f tri_point = triangle._aclPoints[(tri_side+2)%3]; - float ref_dist = (ref_point - planeBase) * planeNormal; - float tri_dist = (tri_point - planeBase) * planeNormal; - if (ref_dist * tri_dist > 0.0f) { + if (!verifier->Accept(planeNormal, planeBase, ref_point, tri_point)) { rFaces.clear(); rPoints.clear(); cTria.Discard(); @@ -778,7 +780,7 @@ bool MeshAlgorithm::FillupHole(const std::vector& boundary, } // we know to have filled a polygon, now check for the orientation - if ( triangle.GetNormal() * rTriangle.GetNormal() <= 0.0f ) { + if (verifier->MustFlip(triangle.GetNormal(), rTriangle.GetNormal())) { for (MeshFacetArray::_TIterator it = rFaces.begin(); it != rFaces.end(); ++it) it->FlipNormal(); } diff --git a/src/Mod/Mesh/App/Core/Triangulation.cpp b/src/Mod/Mesh/App/Core/Triangulation.cpp index 4dae7c8a8c..cdd5ed0a9e 100644 --- a/src/Mod/Mesh/App/Core/Triangulation.cpp +++ b/src/Mod/Mesh/App/Core/Triangulation.cpp @@ -39,13 +39,64 @@ using namespace MeshCore; +bool TriangulationVerifier::Accept(const Base::Vector3f& n, + const Base::Vector3f& p1, + const Base::Vector3f& p2, + const Base::Vector3f& p3) const +{ + float ref_dist = (p2 - p1) * n; + float tri_dist = (p3 - p1) * n; + return (ref_dist * tri_dist <= 0.0f); +} + +bool TriangulationVerifier::MustFlip(const Base::Vector3f& n1, + const Base::Vector3f& n2) const +{ + return n1.Dot(n2) <= 0.0f; +} + +bool TriangulationVerifierV2::Accept(const Base::Vector3f& n, + const Base::Vector3f& p1, + const Base::Vector3f& p2, + const Base::Vector3f& p3) const +{ + float ref_dist = (p2 - p1) * n; + float tri_dist = (p3 - p1) * n; + float prod = ref_dist * tri_dist; + (void)prod; + return true; +} + +bool TriangulationVerifierV2::MustFlip(const Base::Vector3f& n1, + const Base::Vector3f& n2) const +{ + float dot = n1.Dot(n2); + (void)dot; + return false; +} + +// ---------------------------------------------------------------------------- + AbstractPolygonTriangulator::AbstractPolygonTriangulator() { _discard = false; + _verifier = new TriangulationVerifier(); } AbstractPolygonTriangulator::~AbstractPolygonTriangulator() { + delete _verifier; +} + +TriangulationVerifier* AbstractPolygonTriangulator::GetVerifier() const +{ + return _verifier; +} + +void AbstractPolygonTriangulator::SetVerifier(TriangulationVerifier* v) +{ + delete _verifier; + _verifier = v; } void AbstractPolygonTriangulator::SetPolygon(const std::vector& raclPoints) diff --git a/src/Mod/Mesh/App/Core/Triangulation.h b/src/Mod/Mesh/App/Core/Triangulation.h index ff5dfdd5c8..9cb8203b17 100644 --- a/src/Mod/Mesh/App/Core/Triangulation.h +++ b/src/Mod/Mesh/App/Core/Triangulation.h @@ -31,6 +31,30 @@ namespace MeshCore { class MeshKernel; +class MeshExport TriangulationVerifier +{ +public: + TriangulationVerifier() {} + virtual ~TriangulationVerifier() {} + virtual bool Accept(const Base::Vector3f& n, + const Base::Vector3f& p1, + const Base::Vector3f& p2, + const Base::Vector3f& p3) const; + virtual bool MustFlip(const Base::Vector3f& n1, + const Base::Vector3f& n2) const; +}; + +class MeshExport TriangulationVerifierV2 : public TriangulationVerifier +{ +public: + virtual bool Accept(const Base::Vector3f& n, + const Base::Vector3f& p1, + const Base::Vector3f& p2, + const Base::Vector3f& p3) const; + virtual bool MustFlip(const Base::Vector3f& n1, + const Base::Vector3f& n2) const; +}; + class MeshExport AbstractPolygonTriangulator { public: @@ -40,6 +64,12 @@ public: /** Sets the polygon to be triangulated. */ void SetPolygon(const std::vector& raclPoints); void SetIndices(const std::vector& d) {_indices = d;} + /** Set a verifier object that checks if the generated triangulation + * can be accepted and added to the mesh kernel. + * The triangulator takes ownership of the passed verifier. + */ + void SetVerifier(TriangulationVerifier* v); + TriangulationVerifier* GetVerifier() const; /** Usually the created faces use the indices of the polygon points * from [0, n]. If the faces should be appended to an existing mesh * they may need to be reindexed from the calling instance. @@ -108,6 +138,7 @@ protected: std::vector _triangles; std::vector _facets; std::vector _info; + TriangulationVerifier* _verifier; }; /** diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index dcdacee715..0c7c10c4a4 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -1168,6 +1168,7 @@ PyObject* MeshPy::fillupHoles(PyObject *args) } MeshPropertyLock lock(this->parentProperty); + tria->SetVerifier(new MeshCore::TriangulationVerifierV2); getMeshObjectPtr()->fillupHoles(len, level, *tria); } catch (const Base::Exception& e) {