diff --git a/src/Mod/Mesh/App/Core/Degeneration.cpp b/src/Mod/Mesh/App/Core/Degeneration.cpp index 5b1c47902..47ca4afc1 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.cpp +++ b/src/Mod/Mesh/App/Core/Degeneration.cpp @@ -448,68 +448,61 @@ bool MeshEvalInternalFacets::Evaluate() bool MeshEvalDegeneratedFacets::Evaluate() { - MeshFacetIterator it(_rclMesh); - for ( it.Init(); it.More(); it.Next() ) - { - if ( it->IsDegenerated() ) - return false; - } + MeshFacetIterator it(_rclMesh); + for (it.Init(); it.More(); it.Next()) { + if (it->IsDegenerated(fEpsilon)) + return false; + } - return true; + return true; } unsigned long MeshEvalDegeneratedFacets::CountEdgeTooSmall (float fMinEdgeLength) const { - MeshFacetIterator clFIter(_rclMesh); - unsigned long k = 0; + MeshFacetIterator clFIter(_rclMesh); + unsigned long k = 0; - while (clFIter.EndReached() == false) - { - for ( int i = 0; i < 3; i++) - { - if (Base::Distance(clFIter->_aclPoints[i], clFIter->_aclPoints[(i+1)%3]) < fMinEdgeLength) - k++; + while (clFIter.EndReached() == false) { + for (int i = 0; i < 3; i++) { + if (Base::Distance(clFIter->_aclPoints[i], clFIter->_aclPoints[(i+1)%3]) < fMinEdgeLength) + k++; + } + ++clFIter; } - ++clFIter; - } - return k; + return k; } std::vector MeshEvalDegeneratedFacets::GetIndices() const { - std::vector aInds; - MeshFacetIterator it(_rclMesh); - for ( it.Init(); it.More(); it.Next() ) - { - if ( it->IsDegenerated() ) - aInds.push_back(it.Position()); - } + std::vector aInds; + MeshFacetIterator it(_rclMesh); + for (it.Init(); it.More(); it.Next()) { + if (it->IsDegenerated(fEpsilon)) + aInds.push_back(it.Position()); + } - return aInds; + return aInds; } bool MeshFixDegeneratedFacets::Fixup() { - MeshTopoAlgorithm cTopAlg(_rclMesh); + MeshTopoAlgorithm cTopAlg(_rclMesh); - MeshFacetIterator it(_rclMesh); - for ( it.Init(); it.More(); it.Next() ) - { - if ( it->IsDegenerated() ) - { - unsigned long uCt = _rclMesh.CountFacets(); - unsigned long uId = it.Position(); - cTopAlg.RemoveDegeneratedFacet(uId); - if ( uCt != _rclMesh.CountFacets() ) - { - // due to a modification of the array the iterator became invalid - it.Set(uId-1); - } + MeshFacetIterator it(_rclMesh); + for (it.Init(); it.More(); it.Next()) { + if (it->IsDegenerated(fEpsilon)) { + unsigned long uCt = _rclMesh.CountFacets(); + unsigned long uId = it.Position(); + cTopAlg.RemoveDegeneratedFacet(uId); + if (uCt != _rclMesh.CountFacets()) { + // due to a modification of the array the iterator became invalid + it.Set(uId-1); + } + } } - } - return true; + return true; } unsigned long MeshFixDegeneratedFacets::RemoveEdgeTooSmall (float fMinEdgeLength, float fMinEdgeAngle) @@ -610,97 +603,91 @@ unsigned long MeshFixDegeneratedFacets::RemoveEdgeTooSmall (float fMinEdgeLength bool MeshEvalDeformedFacets::Evaluate() { - MeshFacetIterator it(_rclMesh); - for ( it.Init(); it.More(); it.Next() ) - { - if ( it->IsDeformed() ) - return false; - } + MeshFacetIterator it(_rclMesh); + for (it.Init(); it.More(); it.Next()) { + if (it->IsDeformed()) + return false; + } - return true; + return true; } std::vector MeshEvalDeformedFacets::GetIndices() const { - std::vector aInds; - MeshFacetIterator it(_rclMesh); - for ( it.Init(); it.More(); it.Next() ) - { - if ( it->IsDeformed() ) - aInds.push_back(it.Position()); - } + std::vector aInds; + MeshFacetIterator it(_rclMesh); + for (it.Init(); it.More(); it.Next()) { + if (it->IsDeformed()) + aInds.push_back(it.Position()); + } - return aInds; + return aInds; } bool MeshFixDeformedFacets::Fixup() { - Base::Vector3f u,v; - MeshTopoAlgorithm cTopAlg(_rclMesh); + Base::Vector3f u,v; + MeshTopoAlgorithm cTopAlg(_rclMesh); - MeshFacetIterator it(_rclMesh); - for ( it.Init(); it.More(); it.Next() ) - { - // possibly deformed but not degenerated - if ( !it->IsDegenerated() ) - { - // store the angles to avoid to compute twice - float fCosAngles[3] = {0,0,0}; - bool done=false; + MeshFacetIterator it(_rclMesh); + for (it.Init(); it.More(); it.Next()) { + // possibly deformed but not degenerated + if (!it->IsDegenerated(fEpsilon)) { + // store the angles to avoid to compute twice + float fCosAngles[3] = {0,0,0}; + bool done=false; - for (int i=0; i<3; i++) - { - u = it->_aclPoints[(i+1)%3]-it->_aclPoints[i]; - v = it->_aclPoints[(i+2)%3]-it->_aclPoints[i]; - u.Normalize(); - v.Normalize(); + for (int i=0; i<3; i++) { + u = it->_aclPoints[(i+1)%3]-it->_aclPoints[i]; + v = it->_aclPoints[(i+2)%3]-it->_aclPoints[i]; + u.Normalize(); + v.Normalize(); - float fCosAngle = u * v; - fCosAngles[i] = fCosAngle; - } + float fCosAngle = u * v; + fCosAngles[i] = fCosAngle; + } - // first check for angle > 120 deg: in this case we swap with the opposite edge - for (int i=0; i<3; i++) - { - float fCosAngle = fCosAngles[i]; - if (fCosAngle < -0.5f) { - const MeshFacet& face = it.GetReference(); - unsigned long uNeighbour = face._aulNeighbours[(i+1)%3]; - if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) { - cTopAlg.SwapEdge(it.Position(), uNeighbour); - done = true; - } - break; + // first check for angle > 120 deg: in this case we swap with the opposite edge + for (int i=0; i<3; i++) { + float fCosAngle = fCosAngles[i]; + if (fCosAngle < -0.5f) { + const MeshFacet& face = it.GetReference(); + unsigned long uNeighbour = face._aulNeighbours[(i+1)%3]; + if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) { + cTopAlg.SwapEdge(it.Position(), uNeighbour); + done = true; + } + break; + } + } + + // we have swapped already + if (done) + continue; + + // now check for angle < 30 deg: in this case we swap with one of the edges the corner is part of + for (int j=0; j<3; j++) { + float fCosAngle = fCosAngles[j]; + if (fCosAngle > 0.86f) { + const MeshFacet& face = it.GetReference(); + + unsigned long uNeighbour = face._aulNeighbours[j]; + if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) { + cTopAlg.SwapEdge(it.Position(), uNeighbour); + break; + } + + uNeighbour = face._aulNeighbours[(j+2)%3]; + if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) { + cTopAlg.SwapEdge(it.Position(), uNeighbour); + break; + } + } + } } - } - - // we have swapped already - if (done) - continue; - - // now check for angle < 30 deg: in this case we swap with one of the edges the corner is part of - for (int j=0; j<3; j++) - { - float fCosAngle = fCosAngles[j]; - if (fCosAngle > 0.86f) { - const MeshFacet& face = it.GetReference(); - - unsigned long uNeighbour = face._aulNeighbours[j]; - if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) { - cTopAlg.SwapEdge(it.Position(), uNeighbour); - break; - } - uNeighbour = face._aulNeighbours[(j+2)%3]; - if (uNeighbour!=ULONG_MAX && cTopAlg.ShouldSwapEdge(it.Position(), uNeighbour, fMaxAngle)) { - cTopAlg.SwapEdge(it.Position(), uNeighbour); - break; - } - } - } } - } - return true; + return true; } // ---------------------------------------------------------------------- diff --git a/src/Mod/Mesh/App/Core/Degeneration.h b/src/Mod/Mesh/App/Core/Degeneration.h index eba5e7bf9..08df12851 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.h +++ b/src/Mod/Mesh/App/Core/Degeneration.h @@ -280,7 +280,8 @@ public: /** * Construction. */ - MeshEvalDegeneratedFacets (const MeshKernel &rclM) : MeshEvaluation( rclM ) { } + MeshEvalDegeneratedFacets (const MeshKernel &rclM, float fEps) + : MeshEvaluation(rclM), fEpsilon(fEps) {} /** * Destruction. */ @@ -297,6 +298,9 @@ public: * Returns the indices of all corrupt facets. */ std::vector GetIndices() const; + +private: + float fEpsilon; }; /** @@ -310,7 +314,8 @@ public: /** * Construction. */ - MeshFixDegeneratedFacets (MeshKernel &rclM) : MeshValidation( rclM ) { } + MeshFixDegeneratedFacets (MeshKernel &rclM, float fEps) + : MeshValidation(rclM), fEpsilon(fEps) { } /** * Destruction. */ @@ -325,6 +330,8 @@ public: */ unsigned long RemoveEdgeTooSmall (float fMinEdgeLength = MeshDefinitions::_fMinPointDistance, float fMinEdgeAngle = MeshDefinitions::_fMinEdgeAngle); +private: + float fEpsilon; }; /** @@ -367,7 +374,8 @@ public: /** * Construction. */ - MeshFixDeformedFacets (MeshKernel &rclM, float fAngle) : MeshValidation( rclM ), fMaxAngle(fAngle) { } + MeshFixDeformedFacets (MeshKernel &rclM, float fAngle, float fEps) + : MeshValidation(rclM), fMaxAngle(fAngle), fEpsilon(fEps) { } /** * Destruction. */ @@ -379,6 +387,7 @@ public: private: float fMaxAngle; + float fEpsilon; }; /** diff --git a/src/Mod/Mesh/App/Core/Elements.cpp b/src/Mod/Mesh/App/Core/Elements.cpp index 66b688ff5..d1f0c4aca 100644 --- a/src/Mod/Mesh/App/Core/Elements.cpp +++ b/src/Mod/Mesh/App/Core/Elements.cpp @@ -388,8 +388,14 @@ void MeshGeomFacet::Enlarge (float fDist) _aclPoints[2] = clPNew[2]; } -bool MeshGeomFacet::IsDegenerated() const +bool MeshGeomFacet::IsDegenerated(float epsilon) const { + // if we do a strict test then compute the area + if (epsilon == 0) { + float fArea = Area(); + return fArea < epsilon; + } + // The triangle has the points A,B,C where we can define the vector u and v // u = b-a and v = c-a. Then we define the line g: r = a+t*u and the plane // E: (x-c)*u=0. The intersection point of g and E is S. @@ -409,11 +415,16 @@ bool MeshGeomFacet::IsDegenerated() const // BTW (u*u)*(v*v)-(u*v)*(u*v) is the same as (uxv)*(uxv). Base::Vector3f u = _aclPoints[1] - _aclPoints[0]; Base::Vector3f v = _aclPoints[2] - _aclPoints[0]; - float eps = MeshDefinitions::_fMinPointDistanceP2; - float uu = u*u; if (uu < eps) return true; - float vv = v*v; if (vv < eps) return true; + float eps = epsilon; + float uu = u*u; + if (uu < eps) + return true; + float vv = v*v; + if (vv < eps) + return true; float uv = u*v; - if (uu*vv-uv*uv < eps*std::max(uu,vv)) + float crosssqr = uu*vv-uv*uv; + if (crosssqr < eps*std::max(uu,vv)) return true; return false; } diff --git a/src/Mod/Mesh/App/Core/Elements.h b/src/Mod/Mesh/App/Core/Elements.h index 0da635cea..46c390c57 100644 --- a/src/Mod/Mesh/App/Core/Elements.h +++ b/src/Mod/Mesh/App/Core/Elements.h @@ -358,7 +358,7 @@ public: * Checks whether the triangle is degenerated. A triangle is degenerated if its area * is less than an epsilon. */ - bool IsDegenerated() const; + bool IsDegenerated(float epsilon) const; /** * Checks whether the triangle is deformed. The definition of a deformed triangles is not as strong * as the definition of a degenerated triangle. A triangle is deformed if the maximum angle exceeds 120 deg diff --git a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp index b559c9ed9..71e40e3f9 100644 --- a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp +++ b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp @@ -38,6 +38,7 @@ #include "Algorithm.h" #include "Evaluation.h" #include "Triangulation.h" +#include "Definitions.h" #include using namespace MeshCore; @@ -585,10 +586,10 @@ bool MeshTopoAlgorithm::IsSwapEdgeLegal(unsigned long ulFacetPos, unsigned long // do not allow to create degenerated triangles MeshGeomFacet cT3(cP4, cP3, cP1); - if ( cT3.IsDegenerated() ) + if ( cT3.IsDegenerated(MeshDefinitions::_fMinPointDistanceP2) ) return false; MeshGeomFacet cT4(cP3, cP4, cP2); - if ( cT4.IsDegenerated() ) + if ( cT4.IsDegenerated(MeshDefinitions::_fMinPointDistanceP2) ) return false; // We must make sure that the two adjacent triangles builds a convex polygon, otherwise diff --git a/src/Mod/Mesh/App/FacetPy.xml b/src/Mod/Mesh/App/FacetPy.xml index 47ceb3de4..9d1c8df51 100644 --- a/src/Mod/Mesh/App/FacetPy.xml +++ b/src/Mod/Mesh/App/FacetPy.xml @@ -75,5 +75,11 @@ Get a list of intersection points with another triangle. - - \ No newline at end of file + + + The area of the facet + + + + + diff --git a/src/Mod/Mesh/App/FacetPyImp.cpp b/src/Mod/Mesh/App/FacetPyImp.cpp index 6c9ac1d36..610264f51 100644 --- a/src/Mod/Mesh/App/FacetPyImp.cpp +++ b/src/Mod/Mesh/App/FacetPyImp.cpp @@ -25,8 +25,8 @@ #include "Mesh.h" #include "Facet.h" -#include "FacetPy.h" -#include "FacetPy.cpp" +#include +#include #include @@ -170,6 +170,17 @@ Py::Tuple FacetPy::getNeighbourIndices(void) const return idxTuple; } +Py::Float FacetPy::getArea(void) const +{ + FacetPy::PointerType face = this->getFacetPtr(); + if (!face->isBound()) + { return Py::Float(0.0); } + + const MeshCore::MeshKernel& kernel = face->Mesh->getKernel(); + MeshCore::MeshGeomFacet tria = kernel.GetFacet(face->Index); + return Py::Float(tria.Area()); +} + PyObject *FacetPy::getCustomAttributes(const char* attr) const { return 0; diff --git a/src/Mod/Mesh/App/FeatureMeshDefects.cpp b/src/Mod/Mesh/App/FeatureMeshDefects.cpp index a618b5397..3cea2f031 100644 --- a/src/Mod/Mesh/App/FeatureMeshDefects.cpp +++ b/src/Mod/Mesh/App/FeatureMeshDefects.cpp @@ -44,6 +44,7 @@ PROPERTY_SOURCE(Mesh::FixDefects, Mesh::Feature) FixDefects::FixDefects() { ADD_PROPERTY(Source ,(0)); + ADD_PROPERTY(Epsilon ,(0)); } FixDefects::~FixDefects() @@ -223,7 +224,7 @@ App::DocumentObjectExecReturn *FixDegenerations::execute(void) Mesh::PropertyMeshKernel* kernel = static_cast(prop); std::auto_ptr mesh(new MeshObject); *mesh = kernel->getValue(); - mesh->validateDegenerations(); + mesh->validateDegenerations(static_cast(Epsilon.getValue())); this->Mesh.setValuePtr(mesh.release()); } @@ -252,7 +253,8 @@ App::DocumentObjectExecReturn *FixDeformations::execute(void) Mesh::PropertyMeshKernel* kernel = static_cast(prop); std::auto_ptr mesh(new MeshObject); *mesh = kernel->getValue(); - mesh->validateDeformations((float)MaxAngle.getValue()); + mesh->validateDeformations(static_cast(MaxAngle.getValue()), + static_cast(Epsilon.getValue())); this->Mesh.setValuePtr(mesh.release()); } diff --git a/src/Mod/Mesh/App/FeatureMeshDefects.h b/src/Mod/Mesh/App/FeatureMeshDefects.h index e57f59580..c34da4f66 100644 --- a/src/Mod/Mesh/App/FeatureMeshDefects.h +++ b/src/Mod/Mesh/App/FeatureMeshDefects.h @@ -24,6 +24,7 @@ #ifndef MESH_FEATURE_MESH_DEFECTS_H #define MESH_FEATURE_MESH_DEFECTS_H +#include #include #include "MeshFeature.h" @@ -46,6 +47,7 @@ public: /** @name Properties */ //@{ App::PropertyLink Source; + App::PropertyFloat Epsilon; //@} /** @name methods override Feature */ diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index a2dbe2a1e..38fc447b8 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -1240,6 +1240,10 @@ void MeshObject::removeNonManifolds() f_fix.Fixup(); deletedFacets(f_fix.GetDeletedFaces()); } +} + +void MeshObject::removeNonManifoldPoints() +{ MeshCore::MeshEvalPointManifolds p_eval(_kernel); if (!p_eval.Evaluate()) { std::vector faces; @@ -1371,19 +1375,19 @@ void MeshObject::validateIndices() this->_segments.clear(); } -void MeshObject::validateDeformations(float fMaxAngle) +void MeshObject::validateDeformations(float fMaxAngle, float fEps) { unsigned long count = _kernel.CountFacets(); - MeshCore::MeshFixDeformedFacets eval(_kernel, fMaxAngle); + MeshCore::MeshFixDeformedFacets eval(_kernel, fMaxAngle, fEps); eval.Fixup(); if (_kernel.CountFacets() < count) this->_segments.clear(); } -void MeshObject::validateDegenerations() +void MeshObject::validateDegenerations(float fEps) { unsigned long count = _kernel.CountFacets(); - MeshCore::MeshFixDegeneratedFacets eval(_kernel); + MeshCore::MeshFixDegeneratedFacets eval(_kernel, fEps); eval.Fixup(); if (_kernel.CountFacets() < count) this->_segments.clear(); diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index 30d1506b0..c448f0626 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -270,12 +270,13 @@ public: void flipNormals(); void harmonizeNormals(); void validateIndices(); - void validateDeformations(float fMaxAngle); - void validateDegenerations(); + void validateDeformations(float fMaxAngle, float fEps); + void validateDegenerations(float fEps); void removeDuplicatedPoints(); void removeDuplicatedFacets(); bool hasNonManifolds() const; void removeNonManifolds(); + void removeNonManifoldPoints(); bool hasSelfIntersections() const; void removeSelfIntersections(); void removeSelfIntersections(const std::vector&); diff --git a/src/Mod/Mesh/App/MeshFeaturePy.xml b/src/Mod/Mesh/App/MeshFeaturePy.xml index 1ebf3ff8a..1124f61c2 100644 --- a/src/Mod/Mesh/App/MeshFeaturePy.xml +++ b/src/Mod/Mesh/App/MeshFeaturePy.xml @@ -42,6 +42,11 @@ d.addObject(\"Mesh::Feature\"). Remove non-manifolds + + + Remove non-manifold points + + Repair any invalid indices @@ -78,4 +83,4 @@ d.addObject(\"Mesh::Feature\"). - + diff --git a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp index c89873ce3..cdb6f2c7e 100644 --- a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp +++ b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp @@ -26,12 +26,12 @@ #include #include "Core/Evaluation.h" -#include "MeshPy.h" #include "MeshFeature.h" // inclusion of the generated files (generated out of MeshFeaturePy.xml) -#include "MeshFeaturePy.h" -#include "MeshFeaturePy.cpp" +#include +#include +#include using namespace Mesh; @@ -94,7 +94,18 @@ PyObject* MeshFeaturePy::removeNonManifolds(PyObject *args) MeshObject* kernel = obj->Mesh.startEditing(); kernel->removeNonManifolds(); obj->Mesh.finishEditing(); - Py_Return + Py_Return; +} + +PyObject* MeshFeaturePy::removeNonManifoldPoints(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->removeNonManifoldPoints(); + obj->Mesh.finishEditing(); + Py_Return; } PyObject* MeshFeaturePy::fixIndices(PyObject *args) @@ -114,13 +125,14 @@ PyObject* MeshFeaturePy::fixIndices(PyObject *args) PyObject* MeshFeaturePy::fixDegenerations(PyObject *args) { - if (!PyArg_ParseTuple(args, "")) + float fEpsilon = MeshCore::MeshDefinitions::_fMinPointDistanceP2; + if (!PyArg_ParseTuple(args, "|f", &fEpsilon)) return NULL; PY_TRY { Mesh::Feature* obj = getFeaturePtr(); MeshObject* kernel = obj->Mesh.startEditing(); - kernel->validateDegenerations(); + kernel->validateDegenerations(fEpsilon); obj->Mesh.finishEditing(); } PY_CATCH; diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index 05d483f3e..caeb82a69 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -220,6 +220,11 @@ for c in mesh.getSeparatecomponents(): Remove non-manifolds + + + Remove non-manifold points + + Check if the mesh intersects itself diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 49d52d4d9..d4f5cc091 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -905,6 +905,14 @@ PyObject* MeshPy::removeNonManifolds(PyObject *args) Py_Return } +PyObject* MeshPy::removeNonManifoldPoints(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + getMeshObjectPtr()->removeNonManifoldPoints(); + Py_Return +} + PyObject* MeshPy::hasSelfIntersections(PyObject *args) { if (!PyArg_ParseTuple(args, "")) @@ -1073,11 +1081,12 @@ PyObject* MeshPy::fixIndices(PyObject *args) PyObject* MeshPy::fixDeformations(PyObject *args) { float fMaxAngle; - if (!PyArg_ParseTuple(args, "f", &fMaxAngle)) + float fEpsilon = MeshCore::MeshDefinitions::_fMinPointDistanceP2; + if (!PyArg_ParseTuple(args, "f|f", &fMaxAngle, &fEpsilon)) return NULL; PY_TRY { - getMeshObjectPtr()->validateDeformations(fMaxAngle); + getMeshObjectPtr()->validateDeformations(fMaxAngle, fEpsilon); } PY_CATCH; Py_Return; @@ -1085,11 +1094,12 @@ PyObject* MeshPy::fixDeformations(PyObject *args) PyObject* MeshPy::fixDegenerations(PyObject *args) { - if (!PyArg_ParseTuple(args, "")) + float fEpsilon = MeshCore::MeshDefinitions::_fMinPointDistanceP2; + if (!PyArg_ParseTuple(args, "|f", &fEpsilon)) return NULL; PY_TRY { - getMeshObjectPtr()->validateDegenerations(); + getMeshObjectPtr()->validateDegenerations(fEpsilon); } PY_CATCH; Py_Return; diff --git a/src/Mod/Mesh/Gui/CMakeLists.txt b/src/Mod/Mesh/Gui/CMakeLists.txt index 2a6bd3802..3796e9663 100644 --- a/src/Mod/Mesh/Gui/CMakeLists.txt +++ b/src/Mod/Mesh/Gui/CMakeLists.txt @@ -17,6 +17,7 @@ set(MeshGui_LIBS set(Mesh_MOC_HDRS DlgEvaluateMeshImp.h + DlgEvaluateSettings.h DlgRegularSolidImp.h DlgSettingsMeshView.h DlgSettingsImportExportImp.h @@ -32,6 +33,7 @@ SOURCE_GROUP("Moc" FILES ${Mesh_MOC_SRCS}) set(Dialogs_UIC_SRCS DlgEvaluateMesh.ui + DlgEvaluateSettings.ui DlgRegularSolid.ui DlgSettingsMeshView.ui DlgSettingsImportExport.ui @@ -46,6 +48,9 @@ SET(Dialogs_SRCS DlgEvaluateMesh.ui DlgEvaluateMeshImp.cpp DlgEvaluateMeshImp.h + DlgEvaluateSettings.ui + DlgEvaluateSettings.cpp + DlgEvaluateSettings.h DlgRegularSolid.ui DlgRegularSolidImp.cpp DlgRegularSolidImp.h diff --git a/src/Mod/Mesh/Gui/DlgEvaluateMesh.ui b/src/Mod/Mesh/Gui/DlgEvaluateMesh.ui index 0558a5ffc..e5bcc4c03 100644 --- a/src/Mod/Mesh/Gui/DlgEvaluateMesh.ui +++ b/src/Mod/Mesh/Gui/DlgEvaluateMesh.ui @@ -885,7 +885,7 @@ - QDialogButtonBox::Close|QDialogButtonBox::Help + QDialogButtonBox::Close|QDialogButtonBox::Open|QDialogButtonBox::Reset diff --git a/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.cpp b/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.cpp index 06a8c4b31..e91c3b42e 100644 --- a/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.cpp +++ b/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.cpp @@ -28,6 +28,8 @@ #endif #include "DlgEvaluateMeshImp.h" +#include "ui_DlgEvaluateMesh.h" +#include "DlgEvaluateSettings.h" #include #include @@ -72,29 +74,118 @@ void CleanupHandler::cleanup() class DlgEvaluateMeshImp::Private { public: - Private() : meshFeature(0), view(0) + Private() + : meshFeature(0) + , view(0) + , enableFoldsCheck(false) + , checkNonManfoldPoints(false) + , strictlyDegenerated(true) + , epsilonDegenerated(0.0f) { } ~Private() { } + void showFoldsFunction(bool on) + { + ui.label_9->setVisible(on); + ui.line_9->setVisible(on); + ui.checkFoldsButton->setVisible(on); + ui.analyzeFoldsButton->setVisible(on); + ui.repairFoldsButton->setVisible(on); + } + + Ui_DlgEvaluateMesh ui; std::map vp; Mesh::Feature* meshFeature; QPointer view; std::vector self_intersections; + bool enableFoldsCheck; + bool checkNonManfoldPoints; + bool strictlyDegenerated; + float epsilonDegenerated; }; /* TRANSLATOR MeshGui::DlgEvaluateMeshImp */ -void DlgEvaluateMeshImp::changeEvent(QEvent *e) -{ - if (e->type() == QEvent::LanguageChange) { - this->retranslateUi(this); - meshNameButton->setItemText(0, tr("No selection")); - } - QDialog::changeEvent(e); -} +/** + * Constructs a DlgEvaluateMeshImp which is a child of 'parent', with the + * widget flags set to 'f'. + */ +DlgEvaluateMeshImp::DlgEvaluateMeshImp(QWidget* parent, Qt::WindowFlags fl) + : QDialog(parent, fl), d(new Private()) +{ + d->ui.setupUi(this); + d->ui.line->setFrameShape(QFrame::HLine); + d->ui.line->setFrameShadow(QFrame::Sunken); + d->ui.line_2->setFrameShape(QFrame::HLine); + d->ui.line_2->setFrameShadow(QFrame::Sunken); + d->ui.line_3->setFrameShape(QFrame::HLine); + d->ui.line_3->setFrameShadow(QFrame::Sunken); + d->ui.line_4->setFrameShape(QFrame::HLine); + d->ui.line_4->setFrameShadow(QFrame::Sunken); + d->ui.line_5->setFrameShape(QFrame::HLine); + d->ui.line_5->setFrameShadow(QFrame::Sunken); + d->ui.line_6->setFrameShape(QFrame::HLine); + d->ui.line_6->setFrameShadow(QFrame::Sunken); + d->ui.line_7->setFrameShape(QFrame::HLine); + d->ui.line_7->setFrameShadow(QFrame::Sunken); + d->ui.line_8->setFrameShape(QFrame::HLine); + d->ui.line_8->setFrameShadow(QFrame::Sunken); + + connect(d->ui.buttonBox, SIGNAL (helpRequested()), + Gui::getMainWindow(), SLOT (whatsThis())); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/Mod/Mesh/Evaluation"); + d->checkNonManfoldPoints = hGrp->GetBool("CheckNonManifoldPoints", false); + d->enableFoldsCheck = hGrp->GetBool("EnableFoldsCheck", false); + d->strictlyDegenerated = hGrp->GetBool("StrictlyDegenerated", true); + if (d->strictlyDegenerated) + d->epsilonDegenerated = 0.0f; + else + d->epsilonDegenerated = MeshCore::MeshDefinitions::_fMinPointDistanceP2; + + d->showFoldsFunction(d->enableFoldsCheck); + + QPushButton* button = d->ui.buttonBox->button(QDialogButtonBox::Open); + button->setText(tr("Settings...")); + + // try to attach to the active document + this->on_refreshButton_clicked(); +} + +/** + * Destroys the object and frees any allocated resources + */ +DlgEvaluateMeshImp::~DlgEvaluateMeshImp() +{ + // no need to delete child widgets, Qt does it all for us + for (std::map::iterator it = d->vp.begin(); it != d->vp.end(); ++it) { + if (d->view) + d->view->getViewer()->removeViewProvider(it->second); + delete it->second; + } + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/Mod/Mesh/Evaluation"); + hGrp->SetBool("CheckNonManifoldPoints", d->checkNonManfoldPoints); + hGrp->SetBool("EnableFoldsCheck", d->enableFoldsCheck); + hGrp->SetBool("StrictlyDegenerated", d->strictlyDegenerated); + + d->vp.clear(); + delete d; +} + +void DlgEvaluateMeshImp::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::LanguageChange) { + d->ui.retranslateUi(this); + d->ui.meshNameButton->setItemText(0, tr("No selection")); + } + QDialog::changeEvent(e); +} void DlgEvaluateMeshImp::slotCreatedObject(const App::DocumentObject& Obj) { @@ -102,7 +193,7 @@ void DlgEvaluateMeshImp::slotCreatedObject(const App::DocumentObject& Obj) if (Obj.getTypeId().isDerivedFrom(Mesh::Feature::getClassTypeId())) { QString label = QString::fromUtf8(Obj.Label.getValue()); QString name = QString::fromLatin1(Obj.getNameInDocument()); - meshNameButton->addItem(label, name); + d->ui.meshNameButton->addItem(label, name); } } @@ -110,10 +201,10 @@ void DlgEvaluateMeshImp::slotDeletedObject(const App::DocumentObject& Obj) { // remove mesh objects from the list if (Obj.getTypeId().isDerivedFrom(Mesh::Feature::getClassTypeId())) { - int index = meshNameButton->findData(QString::fromLatin1(Obj.getNameInDocument())); + int index = d->ui.meshNameButton->findData(QString::fromLatin1(Obj.getNameInDocument())); if (index > 0) { - meshNameButton->removeItem(index); - meshNameButton->setDisabled(meshNameButton->count() < 2); + d->ui.meshNameButton->removeItem(index); + d->ui.meshNameButton->setDisabled(d->ui.meshNameButton->count() < 2); } } @@ -121,7 +212,7 @@ void DlgEvaluateMeshImp::slotDeletedObject(const App::DocumentObject& Obj) if (&Obj == d->meshFeature) { removeViewProviders(); d->meshFeature = 0; - meshNameButton->setCurrentIndex(0); + d->ui.meshNameButton->setCurrentIndex(0); cleanInformation(); d->self_intersections.clear(); } @@ -142,8 +233,8 @@ void DlgEvaluateMeshImp::slotChangedObject(const App::DocumentObject& Obj, const strcmp(Prop.getName(), "Label") == 0) { QString label = QString::fromUtf8(Obj.Label.getValue()); QString name = QString::fromLatin1(Obj.getNameInDocument()); - int index = meshNameButton->findData(name); - meshNameButton->setItemText(index, label); + int index = d->ui.meshNameButton->findData(name); + d->ui.meshNameButton->setItemText(index, label); } } } @@ -165,57 +256,6 @@ void DlgEvaluateMeshImp::slotDeletedDocument(const App::Document& Doc) } } -/** - * Constructs a DlgEvaluateMeshImp which is a child of 'parent', with the - * name 'name' and widget flags set to 'f' - * - * The dialog will by default be modeless, unless you set 'modal' to - * true to construct a modal dialog. - */ -DlgEvaluateMeshImp::DlgEvaluateMeshImp(QWidget* parent, Qt::WindowFlags fl) - : QDialog(parent, fl), d(new Private()) -{ - this->setupUi(this); - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - line_2->setFrameShape(QFrame::HLine); - line_2->setFrameShadow(QFrame::Sunken); - line_3->setFrameShape(QFrame::HLine); - line_3->setFrameShadow(QFrame::Sunken); - line_4->setFrameShape(QFrame::HLine); - line_4->setFrameShadow(QFrame::Sunken); - line_5->setFrameShape(QFrame::HLine); - line_5->setFrameShadow(QFrame::Sunken); - line_6->setFrameShape(QFrame::HLine); - line_6->setFrameShadow(QFrame::Sunken); - line_7->setFrameShape(QFrame::HLine); - line_7->setFrameShadow(QFrame::Sunken); - line_8->setFrameShape(QFrame::HLine); - line_8->setFrameShadow(QFrame::Sunken); - - connect(buttonBox, SIGNAL (helpRequested()), - Gui::getMainWindow(), SLOT (whatsThis())); - - // try to attach to the active document - this->on_refreshButton_clicked(); -} - -/** - * Destroys the object and frees any allocated resources - */ -DlgEvaluateMeshImp::~DlgEvaluateMeshImp() -{ - // no need to delete child widgets, Qt does it all for us - for (std::map::iterator it = d->vp.begin(); it != d->vp.end(); ++it) { - if (d->view) - d->view->getViewer()->removeViewProvider(it->second); - delete it->second; - } - - d->vp.clear(); - delete d; -} - void DlgEvaluateMeshImp::setMesh(Mesh::Feature* m) { App::Document* doc = m->getDocument(); @@ -224,11 +264,11 @@ void DlgEvaluateMeshImp::setMesh(Mesh::Feature* m) refreshList(); - int ct = meshNameButton->count(); + int ct = d->ui.meshNameButton->count(); QString objName = QString::fromLatin1(m->getNameInDocument()); for (int i=1; iitemData(i).toString() == objName) { - meshNameButton->setCurrentIndex(i); + if (d->ui.meshNameButton->itemData(i).toString() == objName) { + d->ui.meshNameButton->setCurrentIndex(i); on_meshNameButton_activated(i); break; } @@ -272,7 +312,7 @@ void DlgEvaluateMeshImp::removeViewProviders() void DlgEvaluateMeshImp::on_meshNameButton_activated(int i) { - QString item = meshNameButton->itemData(i).toString(); + QString item = d->ui.meshNameButton->itemData(i).toString(); d->meshFeature = 0; std::vector objs = getDocument()->getObjectsOfType(Mesh::Feature::getClassTypeId()); @@ -302,63 +342,63 @@ void DlgEvaluateMeshImp::refreshList() } } - meshNameButton->clear(); - meshNameButton->addItem(tr("No selection")); + d->ui.meshNameButton->clear(); + d->ui.meshNameButton->addItem(tr("No selection")); for (QList >::iterator it = items.begin(); it != items.end(); ++it) - meshNameButton->addItem(it->first, it->second); - meshNameButton->setDisabled(items.empty()); + d->ui.meshNameButton->addItem(it->first, it->second); + d->ui.meshNameButton->setDisabled(items.empty()); cleanInformation(); } void DlgEvaluateMeshImp::showInformation() { - analyzeOrientationButton->setEnabled(true); - analyzeDuplicatedFacesButton->setEnabled(true); - analyzeDuplicatedPointsButton->setEnabled(true); - analyzeNonmanifoldsButton->setEnabled(true); - analyzeDegeneratedButton->setEnabled(true); - analyzeIndicesButton->setEnabled(true); - analyzeSelfIntersectionButton->setEnabled(true); - analyzeFoldsButton->setEnabled(true); - analyzeAllTogether->setEnabled(true); + d->ui.analyzeOrientationButton->setEnabled(true); + d->ui.analyzeDuplicatedFacesButton->setEnabled(true); + d->ui.analyzeDuplicatedPointsButton->setEnabled(true); + d->ui.analyzeNonmanifoldsButton->setEnabled(true); + d->ui.analyzeDegeneratedButton->setEnabled(true); + d->ui.analyzeIndicesButton->setEnabled(true); + d->ui.analyzeSelfIntersectionButton->setEnabled(true); + d->ui.analyzeFoldsButton->setEnabled(true); + d->ui.analyzeAllTogether->setEnabled(true); const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel(); - textLabel4->setText(QString::fromLatin1("%1").arg(rMesh.CountFacets())); - textLabel5->setText(QString::fromLatin1("%1").arg(rMesh.CountEdges())); - textLabel6->setText(QString::fromLatin1("%1").arg(rMesh.CountPoints())); + d->ui.textLabel4->setText(QString::fromLatin1("%1").arg(rMesh.CountFacets())); + d->ui.textLabel5->setText(QString::fromLatin1("%1").arg(rMesh.CountEdges())); + d->ui.textLabel6->setText(QString::fromLatin1("%1").arg(rMesh.CountPoints())); } void DlgEvaluateMeshImp::cleanInformation() { - textLabel4->setText( tr("No information") ); - textLabel5->setText( tr("No information") ); - textLabel6->setText( tr("No information") ); - checkOrientationButton->setText( tr("No information") ); - checkDuplicatedFacesButton->setText( tr("No information") ); - checkDuplicatedPointsButton->setText( tr("No information") ); - checkNonmanifoldsButton->setText( tr("No information") ); - checkDegenerationButton->setText( tr("No information") ); - checkIndicesButton->setText( tr("No information") ); - checkSelfIntersectionButton->setText( tr("No information") ); - checkFoldsButton->setText( tr("No information") ); - analyzeOrientationButton->setDisabled(true); - repairOrientationButton->setDisabled(true); - analyzeDuplicatedFacesButton->setDisabled(true); - repairDuplicatedFacesButton->setDisabled(true); - analyzeDuplicatedPointsButton->setDisabled(true); - repairDuplicatedPointsButton->setDisabled(true); - analyzeNonmanifoldsButton->setDisabled(true); - repairNonmanifoldsButton->setDisabled(true); - analyzeDegeneratedButton->setDisabled(true); - repairDegeneratedButton->setDisabled(true); - analyzeIndicesButton->setDisabled(true); - repairIndicesButton->setDisabled(true); - analyzeSelfIntersectionButton->setDisabled(true); - repairSelfIntersectionButton->setDisabled(true); - analyzeFoldsButton->setDisabled(true); - repairFoldsButton->setDisabled(true); - analyzeAllTogether->setDisabled(true); - repairAllTogether->setDisabled(true); + d->ui.textLabel4->setText( tr("No information") ); + d->ui.textLabel5->setText( tr("No information") ); + d->ui.textLabel6->setText( tr("No information") ); + d->ui.checkOrientationButton->setText( tr("No information") ); + d->ui.checkDuplicatedFacesButton->setText( tr("No information") ); + d->ui.checkDuplicatedPointsButton->setText( tr("No information") ); + d->ui.checkNonmanifoldsButton->setText( tr("No information") ); + d->ui.checkDegenerationButton->setText( tr("No information") ); + d->ui.checkIndicesButton->setText( tr("No information") ); + d->ui.checkSelfIntersectionButton->setText( tr("No information") ); + d->ui.checkFoldsButton->setText( tr("No information") ); + d->ui.analyzeOrientationButton->setDisabled(true); + d->ui.repairOrientationButton->setDisabled(true); + d->ui.analyzeDuplicatedFacesButton->setDisabled(true); + d->ui.repairDuplicatedFacesButton->setDisabled(true); + d->ui.analyzeDuplicatedPointsButton->setDisabled(true); + d->ui.repairDuplicatedPointsButton->setDisabled(true); + d->ui.analyzeNonmanifoldsButton->setDisabled(true); + d->ui.repairNonmanifoldsButton->setDisabled(true); + d->ui.analyzeDegeneratedButton->setDisabled(true); + d->ui.repairDegeneratedButton->setDisabled(true); + d->ui.analyzeIndicesButton->setDisabled(true); + d->ui.repairIndicesButton->setDisabled(true); + d->ui.analyzeSelfIntersectionButton->setDisabled(true); + d->ui.repairSelfIntersectionButton->setDisabled(true); + d->ui.analyzeFoldsButton->setDisabled(true); + d->ui.repairFoldsButton->setDisabled(true); + d->ui.analyzeAllTogether->setDisabled(true); + d->ui.repairAllTogether->setDisabled(true); } void DlgEvaluateMeshImp::on_refreshButton_clicked() @@ -383,7 +423,7 @@ void DlgEvaluateMeshImp::on_checkOrientationButton_clicked() { std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshOrientation"); if (it != d->vp.end()) { - if (checkOrientationButton->isChecked()) + if (d->ui.checkOrientationButton->isChecked()) it->second->show(); else it->second->hide(); @@ -393,15 +433,16 @@ void DlgEvaluateMeshImp::on_checkOrientationButton_clicked() void DlgEvaluateMeshImp::on_analyzeOrientationButton_clicked() { if (d->meshFeature) { - analyzeOrientationButton->setEnabled(false); + d->ui.analyzeOrientationButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel(); MeshEvalOrientation eval(rMesh); std::vector inds = eval.GetIndices(); +#if 0 if (inds.empty() && !eval.Evaluate()) { - checkOrientationButton->setText(tr("Flipped normals found")); + d->ui.checkOrientationButton->setText(tr("Flipped normals found")); MeshEvalFoldOversOnSurface f_eval(rMesh); if (!f_eval.Evaluate()) { qApp->restoreOverrideCursor(); @@ -411,22 +452,24 @@ void DlgEvaluateMeshImp::on_analyzeOrientationButton_clicked() qApp->setOverrideCursor(Qt::WaitCursor); } } - else if (inds.empty()) { - checkOrientationButton->setText( tr("No flipped normals") ); - checkOrientationButton->setChecked(false); - repairOrientationButton->setEnabled(false); + else +#endif + if (inds.empty()) { + d->ui.checkOrientationButton->setText( tr("No flipped normals") ); + d->ui.checkOrientationButton->setChecked(false); + d->ui.repairOrientationButton->setEnabled(false); removeViewProvider( "MeshGui::ViewProviderMeshOrientation" ); } else { - checkOrientationButton->setText( tr("%1 flipped normals").arg(inds.size()) ); - checkOrientationButton->setChecked(true); - repairOrientationButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkOrientationButton->setText( tr("%1 flipped normals").arg(inds.size()) ); + d->ui.checkOrientationButton->setChecked(true); + d->ui.repairOrientationButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider( "MeshGui::ViewProviderMeshOrientation", eval.GetIndices()); } qApp->restoreOverrideCursor(); - analyzeOrientationButton->setEnabled(true); + d->ui.analyzeOrientationButton->setEnabled(true); } } @@ -449,17 +492,28 @@ void DlgEvaluateMeshImp::on_repairOrientationButton_clicked() doc->commitCommand(); doc->getDocument()->recompute(); - repairOrientationButton->setEnabled(false); - checkOrientationButton->setChecked(false); + d->ui.repairOrientationButton->setEnabled(false); + d->ui.checkOrientationButton->setChecked(false); removeViewProvider( "MeshGui::ViewProviderMeshOrientation" ); } } void DlgEvaluateMeshImp::on_checkNonmanifoldsButton_clicked() { - std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshNonManifolds"); + // non-manifold edges + std::map::iterator it; + it = d->vp.find("MeshGui::ViewProviderMeshNonManifolds"); if (it != d->vp.end()) { - if (checkNonmanifoldsButton->isChecked()) + if (d->ui.checkNonmanifoldsButton->isChecked()) + it->second->show(); + else + it->second->hide(); + } + + // non-manifold points + it = d->vp.find("MeshGui::ViewProviderMeshNonManifoldPoints"); + if (it != d->vp.end()) { + if (d->ui.checkNonmanifoldsButton->isChecked()) it->second->show(); else it->second->hide(); @@ -469,27 +523,36 @@ void DlgEvaluateMeshImp::on_checkNonmanifoldsButton_clicked() void DlgEvaluateMeshImp::on_analyzeNonmanifoldsButton_clicked() { if (d->meshFeature) { - analyzeNonmanifoldsButton->setEnabled(false); + d->ui.analyzeNonmanifoldsButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel(); MeshEvalTopology f_eval(rMesh); - MeshEvalPointManifolds p_eval(rMesh); bool ok1 = f_eval.Evaluate(); - bool ok2 = p_eval.Evaluate(); - + bool ok2 = true; + std::vector point_indices; + + if (d->checkNonManfoldPoints) { + MeshEvalPointManifolds p_eval(rMesh); + ok2 = p_eval.Evaluate(); + if (!ok2) + point_indices = p_eval.GetIndices(); + } + if (ok1 && ok2) { - checkNonmanifoldsButton->setText(tr("No non-manifolds")); - checkNonmanifoldsButton->setChecked(false); - repairNonmanifoldsButton->setEnabled(false); + d->ui.checkNonmanifoldsButton->setText(tr("No non-manifolds")); + d->ui.checkNonmanifoldsButton->setChecked(false); + d->ui.repairNonmanifoldsButton->setEnabled(false); removeViewProvider("MeshGui::ViewProviderMeshNonManifolds"); + removeViewProvider("MeshGui::ViewProviderMeshNonManifoldPoints"); } else { - checkNonmanifoldsButton->setText(tr("%1 non-manifolds").arg(f_eval.CountManifolds()+p_eval.CountManifolds())); - checkNonmanifoldsButton->setChecked(true); - repairNonmanifoldsButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkNonmanifoldsButton->setText(tr("%1 non-manifolds").arg(f_eval.CountManifolds()+point_indices.size())); + d->ui.checkNonmanifoldsButton->setChecked(true); + d->ui.repairNonmanifoldsButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); + if (!ok1) { const std::vector >& inds = f_eval.GetIndices(); std::vector indices; @@ -502,13 +565,14 @@ void DlgEvaluateMeshImp::on_analyzeNonmanifoldsButton_clicked() addViewProvider("MeshGui::ViewProviderMeshNonManifolds", indices); } + if (!ok2) { - addViewProvider("MeshGui::ViewProviderMeshNonManifoldPoints", p_eval.GetIndices()); + addViewProvider("MeshGui::ViewProviderMeshNonManifoldPoints", point_indices); } } qApp->restoreOverrideCursor(); - analyzeNonmanifoldsButton->setEnabled(true); + d->ui.analyzeNonmanifoldsButton->setEnabled(true); } } @@ -523,6 +587,12 @@ void DlgEvaluateMeshImp::on_repairNonmanifoldsButton_clicked() Gui::Application::Instance->runCommand( true, "App.getDocument(\"%s\").getObject(\"%s\").removeNonManifolds()" , docName, objName); + + if (d->checkNonManfoldPoints) { + Gui::Application::Instance->runCommand( + true, "App.getDocument(\"%s\").getObject(\"%s\").removeNonManifoldPoints()" + , docName, objName); + } } catch (const Base::Exception& e) { QMessageBox::warning(this, tr("Non-manifolds"), QString::fromLatin1(e.what())); @@ -534,9 +604,10 @@ void DlgEvaluateMeshImp::on_repairNonmanifoldsButton_clicked() doc->commitCommand(); doc->getDocument()->recompute(); - repairNonmanifoldsButton->setEnabled(false); - checkNonmanifoldsButton->setChecked(false); + d->ui.repairNonmanifoldsButton->setEnabled(false); + d->ui.checkNonmanifoldsButton->setChecked(false); removeViewProvider("MeshGui::ViewProviderMeshNonManifolds"); + removeViewProvider("MeshGui::ViewProviderMeshNonManifoldsPoints"); } } @@ -544,7 +615,7 @@ void DlgEvaluateMeshImp::on_checkIndicesButton_clicked() { std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshIndices"); if (it != d->vp.end()) { - if (checkIndicesButton->isChecked()) + if (d->ui.checkIndicesButton->isChecked()) it->second->show(); else it->second->hide(); @@ -554,7 +625,7 @@ void DlgEvaluateMeshImp::on_checkIndicesButton_clicked() void DlgEvaluateMeshImp::on_analyzeIndicesButton_clicked() { if (d->meshFeature) { - analyzeIndicesButton->setEnabled(false); + d->ui.analyzeIndicesButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); @@ -565,42 +636,42 @@ void DlgEvaluateMeshImp::on_analyzeIndicesButton_clicked() MeshEvalNeighbourhood nb(rMesh); if (!rf.Evaluate()) { - checkIndicesButton->setText(tr("Invalid face indices")); - checkIndicesButton->setChecked(true); - repairIndicesButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkIndicesButton->setText(tr("Invalid face indices")); + d->ui.checkIndicesButton->setChecked(true); + d->ui.repairIndicesButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider("MeshGui::ViewProviderMeshIndices", rf.GetIndices()); } else if (!rp.Evaluate()) { - checkIndicesButton->setText(tr("Invalid point indices")); - checkIndicesButton->setChecked(true); - repairIndicesButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkIndicesButton->setText(tr("Invalid point indices")); + d->ui.checkIndicesButton->setChecked(true); + d->ui.repairIndicesButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); //addViewProvider("MeshGui::ViewProviderMeshIndices", rp.GetIndices()); } else if (!cf.Evaluate()) { - checkIndicesButton->setText(tr("Multiple point indices")); - checkIndicesButton->setChecked(true); - repairIndicesButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkIndicesButton->setText(tr("Multiple point indices")); + d->ui.checkIndicesButton->setChecked(true); + d->ui.repairIndicesButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider("MeshGui::ViewProviderMeshIndices", cf.GetIndices()); } else if (!nb.Evaluate()) { - checkIndicesButton->setText(tr("Invalid neighbour indices")); - checkIndicesButton->setChecked(true); - repairIndicesButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkIndicesButton->setText(tr("Invalid neighbour indices")); + d->ui.checkIndicesButton->setChecked(true); + d->ui.repairIndicesButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider("MeshGui::ViewProviderMeshIndices", nb.GetIndices()); } else { - checkIndicesButton->setText(tr("No invalid indices")); - checkIndicesButton->setChecked(false); - repairIndicesButton->setEnabled(false); + d->ui.checkIndicesButton->setText(tr("No invalid indices")); + d->ui.checkIndicesButton->setChecked(false); + d->ui.repairIndicesButton->setEnabled(false); removeViewProvider("MeshGui::ViewProviderMeshIndices"); } qApp->restoreOverrideCursor(); - analyzeIndicesButton->setEnabled(true); + d->ui.analyzeIndicesButton->setEnabled(true); } } @@ -623,8 +694,8 @@ void DlgEvaluateMeshImp::on_repairIndicesButton_clicked() doc->commitCommand(); doc->getDocument()->recompute(); - repairIndicesButton->setEnabled(false); - checkIndicesButton->setChecked(false); + d->ui.repairIndicesButton->setEnabled(false); + d->ui.checkIndicesButton->setChecked(false); removeViewProvider("MeshGui::ViewProviderMeshIndices"); } } @@ -633,7 +704,7 @@ void DlgEvaluateMeshImp::on_checkDegenerationButton_clicked() { std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshDegenerations"); if (it != d->vp.end()) { - if (checkDegenerationButton->isChecked()) + if (d->ui.checkDegenerationButton->isChecked()) it->second->show(); else it->second->hide(); @@ -643,30 +714,30 @@ void DlgEvaluateMeshImp::on_checkDegenerationButton_clicked() void DlgEvaluateMeshImp::on_analyzeDegeneratedButton_clicked() { if (d->meshFeature) { - analyzeDegeneratedButton->setEnabled(false); + d->ui.analyzeDegeneratedButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel(); - MeshEvalDegeneratedFacets eval(rMesh); + MeshEvalDegeneratedFacets eval(rMesh, d->epsilonDegenerated); std::vector degen = eval.GetIndices(); if (degen.empty()) { - checkDegenerationButton->setText(tr("No degenerations")); - checkDegenerationButton->setChecked(false); - repairDegeneratedButton->setEnabled(false); + d->ui.checkDegenerationButton->setText(tr("No degenerations")); + d->ui.checkDegenerationButton->setChecked(false); + d->ui.repairDegeneratedButton->setEnabled(false); removeViewProvider("MeshGui::ViewProviderMeshDegenerations"); } else { - checkDegenerationButton->setText(tr("%1 degenerated faces").arg(degen.size())); - checkDegenerationButton->setChecked(true); - repairDegeneratedButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkDegenerationButton->setText(tr("%1 degenerated faces").arg(degen.size())); + d->ui.checkDegenerationButton->setChecked(true); + d->ui.repairDegeneratedButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider("MeshGui::ViewProviderMeshDegenerations", degen); } qApp->restoreOverrideCursor(); - analyzeDegeneratedButton->setEnabled(true); + d->ui.analyzeDegeneratedButton->setEnabled(true); } } @@ -679,8 +750,8 @@ void DlgEvaluateMeshImp::on_repairDegeneratedButton_clicked() doc->openCommand("Remove degenerated faces"); try { Gui::Application::Instance->runCommand( - true, "App.getDocument(\"%s\").getObject(\"%s\").fixDegenerations()" - , docName, objName); + true, "App.getDocument(\"%s\").getObject(\"%s\").fixDegenerations(%f)" + , docName, objName, d->epsilonDegenerated); } catch (const Base::Exception& e) { QMessageBox::warning(this, tr("Degenerations"), QString::fromLatin1(e.what())); @@ -689,8 +760,8 @@ void DlgEvaluateMeshImp::on_repairDegeneratedButton_clicked() doc->commitCommand(); doc->getDocument()->recompute(); - repairDegeneratedButton->setEnabled(false); - checkDegenerationButton->setChecked(false); + d->ui.repairDegeneratedButton->setEnabled(false); + d->ui.checkDegenerationButton->setChecked(false); removeViewProvider("MeshGui::ViewProviderMeshDegenerations"); } } @@ -699,7 +770,7 @@ void DlgEvaluateMeshImp::on_checkDuplicatedFacesButton_clicked() { std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshDuplicatedFaces"); if (it != d->vp.end()) { - if (checkDuplicatedFacesButton->isChecked()) + if (d->ui.checkDuplicatedFacesButton->isChecked()) it->second->show(); else it->second->hide(); @@ -709,7 +780,7 @@ void DlgEvaluateMeshImp::on_checkDuplicatedFacesButton_clicked() void DlgEvaluateMeshImp::on_analyzeDuplicatedFacesButton_clicked() { if (d->meshFeature) { - analyzeDuplicatedFacesButton->setEnabled(false); + d->ui.analyzeDuplicatedFacesButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); @@ -718,22 +789,22 @@ void DlgEvaluateMeshImp::on_analyzeDuplicatedFacesButton_clicked() std::vector dupl = eval.GetIndices(); if (dupl.empty()) { - checkDuplicatedFacesButton->setText(tr("No duplicated faces")); - checkDuplicatedFacesButton->setChecked(false); - repairDuplicatedFacesButton->setEnabled(false); + d->ui.checkDuplicatedFacesButton->setText(tr("No duplicated faces")); + d->ui.checkDuplicatedFacesButton->setChecked(false); + d->ui.repairDuplicatedFacesButton->setEnabled(false); removeViewProvider("MeshGui::ViewProviderMeshDuplicatedFaces"); } else { - checkDuplicatedFacesButton->setText(tr("%1 duplicated faces").arg(dupl.size())); - checkDuplicatedFacesButton->setChecked(true); - repairDuplicatedFacesButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkDuplicatedFacesButton->setText(tr("%1 duplicated faces").arg(dupl.size())); + d->ui.checkDuplicatedFacesButton->setChecked(true); + d->ui.repairDuplicatedFacesButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider("MeshGui::ViewProviderMeshDuplicatedFaces", dupl); } qApp->restoreOverrideCursor(); - analyzeDuplicatedFacesButton->setEnabled(true); + d->ui.analyzeDuplicatedFacesButton->setEnabled(true); } } @@ -756,8 +827,8 @@ void DlgEvaluateMeshImp::on_repairDuplicatedFacesButton_clicked() doc->commitCommand(); doc->getDocument()->recompute(); - repairDuplicatedFacesButton->setEnabled(false); - checkDuplicatedFacesButton->setChecked(false); + d->ui.repairDuplicatedFacesButton->setEnabled(false); + d->ui.checkDuplicatedFacesButton->setChecked(false); removeViewProvider("MeshGui::ViewProviderMeshDuplicatedFaces"); } } @@ -766,7 +837,7 @@ void DlgEvaluateMeshImp::on_checkDuplicatedPointsButton_clicked() { std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshDuplicatedPoints"); if (it != d->vp.end()) { - if ( checkDuplicatedPointsButton->isChecked() ) + if (d->ui.checkDuplicatedPointsButton->isChecked()) it->second->show(); else it->second->hide(); @@ -776,7 +847,7 @@ void DlgEvaluateMeshImp::on_checkDuplicatedPointsButton_clicked() void DlgEvaluateMeshImp::on_analyzeDuplicatedPointsButton_clicked() { if (d->meshFeature) { - analyzeDuplicatedPointsButton->setEnabled(false); + d->ui.analyzeDuplicatedPointsButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); @@ -784,21 +855,21 @@ void DlgEvaluateMeshImp::on_analyzeDuplicatedPointsButton_clicked() MeshEvalDuplicatePoints eval(rMesh); if (eval.Evaluate()) { - checkDuplicatedPointsButton->setText(tr("No duplicated points")); - checkDuplicatedPointsButton->setChecked(false); - repairDuplicatedPointsButton->setEnabled(false); + d->ui.checkDuplicatedPointsButton->setText(tr("No duplicated points")); + d->ui.checkDuplicatedPointsButton->setChecked(false); + d->ui.repairDuplicatedPointsButton->setEnabled(false); removeViewProvider("MeshGui::ViewProviderMeshDuplicatedPoints"); } else { - checkDuplicatedPointsButton->setText(tr("Duplicated points")); - checkDuplicatedPointsButton->setChecked(true); - repairDuplicatedPointsButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkDuplicatedPointsButton->setText(tr("Duplicated points")); + d->ui.checkDuplicatedPointsButton->setChecked(true); + d->ui.repairDuplicatedPointsButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider("MeshGui::ViewProviderMeshDuplicatedPoints", eval.GetIndices()); } qApp->restoreOverrideCursor(); - analyzeDuplicatedPointsButton->setEnabled(true); + d->ui.analyzeDuplicatedPointsButton->setEnabled(true); } } @@ -821,8 +892,8 @@ void DlgEvaluateMeshImp::on_repairDuplicatedPointsButton_clicked() doc->commitCommand(); doc->getDocument()->recompute(); - repairDuplicatedPointsButton->setEnabled(false); - checkDuplicatedPointsButton->setChecked(false); + d->ui.repairDuplicatedPointsButton->setEnabled(false); + d->ui.checkDuplicatedPointsButton->setChecked(false); removeViewProvider("MeshGui::ViewProviderMeshDuplicatedPoints"); } } @@ -831,7 +902,7 @@ void DlgEvaluateMeshImp::on_checkSelfIntersectionButton_clicked() { std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshSelfIntersections"); if (it != d->vp.end()) { - if ( checkSelfIntersectionButton->isChecked() ) + if (d->ui.checkSelfIntersectionButton->isChecked()) it->second->show(); else it->second->hide(); @@ -841,7 +912,7 @@ void DlgEvaluateMeshImp::on_checkSelfIntersectionButton_clicked() void DlgEvaluateMeshImp::on_analyzeSelfIntersectionButton_clicked() { if (d->meshFeature) { - analyzeSelfIntersectionButton->setEnabled(false); + d->ui.analyzeSelfIntersectionButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); @@ -856,16 +927,17 @@ void DlgEvaluateMeshImp::on_analyzeSelfIntersectionButton_clicked() } if (intersection.empty()) { - checkSelfIntersectionButton->setText(tr("No self-intersections")); - checkSelfIntersectionButton->setChecked(false); - repairSelfIntersectionButton->setEnabled(false); + d->ui.checkSelfIntersectionButton->setText(tr("No self-intersections")); + d->ui.checkSelfIntersectionButton->setChecked(false); + d->ui.repairSelfIntersectionButton->setEnabled(false); removeViewProvider("MeshGui::ViewProviderMeshSelfIntersections"); } else { - checkSelfIntersectionButton->setText(tr("Self-intersections")); - checkSelfIntersectionButton->setChecked(true); - repairSelfIntersectionButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkSelfIntersectionButton->setText(tr("Self-intersections")); + d->ui.checkSelfIntersectionButton->setChecked(true); + d->ui.repairSelfIntersectionButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); + std::vector indices; indices.reserve(2*intersection.size()); std::vector >::iterator it; @@ -879,7 +951,7 @@ void DlgEvaluateMeshImp::on_analyzeSelfIntersectionButton_clicked() } qApp->restoreOverrideCursor(); - analyzeSelfIntersectionButton->setEnabled(true); + d->ui.analyzeSelfIntersectionButton->setEnabled(true); } } @@ -910,8 +982,8 @@ void DlgEvaluateMeshImp::on_repairSelfIntersectionButton_clicked() doc->commitCommand(); doc->getDocument()->recompute(); - repairSelfIntersectionButton->setEnabled(false); - checkSelfIntersectionButton->setChecked(false); + d->ui.repairSelfIntersectionButton->setEnabled(false); + d->ui.checkSelfIntersectionButton->setChecked(false); removeViewProvider("MeshGui::ViewProviderMeshSelfIntersections"); } } @@ -920,7 +992,7 @@ void DlgEvaluateMeshImp::on_checkFoldsButton_clicked() { std::map::iterator it = d->vp.find("MeshGui::ViewProviderMeshFolds"); if (it != d->vp.end()) { - if (checkFoldsButton->isChecked()) + if (d->ui.checkFoldsButton->isChecked()) it->second->show(); else it->second->hide(); @@ -930,7 +1002,7 @@ void DlgEvaluateMeshImp::on_checkFoldsButton_clicked() void DlgEvaluateMeshImp::on_analyzeFoldsButton_clicked() { if (d->meshFeature) { - analyzeFoldsButton->setEnabled(false); + d->ui.analyzeFoldsButton->setEnabled(false); qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); @@ -943,31 +1015,31 @@ void DlgEvaluateMeshImp::on_analyzeFoldsButton_clicked() bool ok3 = f_eval.Evaluate(); if (ok1 && ok2 && ok3) { - checkFoldsButton->setText(tr("No folds on surface")); - checkFoldsButton->setChecked(false); - repairFoldsButton->setEnabled(false); + d->ui.checkFoldsButton->setText(tr("No folds on surface")); + d->ui.checkFoldsButton->setChecked(false); + d->ui.repairFoldsButton->setEnabled(false); removeViewProvider("MeshGui::ViewProviderMeshFolds"); } else { std::vector inds = f_eval.GetIndices(); - std::vector inds1 = s_eval.GetIndices(); - std::vector inds2 = b_eval.GetIndices(); - inds.insert(inds.end(), inds1.begin(), inds1.end()); - inds.insert(inds.end(), inds2.begin(), inds2.end()); - - // remove duplicates - std::sort(inds.begin(), inds.end()); - inds.erase(std::unique(inds.begin(), inds.end()), inds.end()); + std::vector inds1 = s_eval.GetIndices(); + std::vector inds2 = b_eval.GetIndices(); + inds.insert(inds.end(), inds1.begin(), inds1.end()); + inds.insert(inds.end(), inds2.begin(), inds2.end()); + + // remove duplicates + std::sort(inds.begin(), inds.end()); + inds.erase(std::unique(inds.begin(), inds.end()), inds.end()); - checkFoldsButton->setText(tr("%1 folds on surface").arg(inds.size())); - checkFoldsButton->setChecked(true); - repairFoldsButton->setEnabled(true); - repairAllTogether->setEnabled(true); + d->ui.checkFoldsButton->setText(tr("%1 folds on surface").arg(inds.size())); + d->ui.checkFoldsButton->setChecked(true); + d->ui.repairFoldsButton->setEnabled(true); + d->ui.repairAllTogether->setEnabled(true); addViewProvider("MeshGui::ViewProviderMeshFolds", inds); } qApp->restoreOverrideCursor(); - analyzeFoldsButton->setEnabled(true); + d->ui.analyzeFoldsButton->setEnabled(true); } } @@ -992,8 +1064,8 @@ void DlgEvaluateMeshImp::on_repairFoldsButton_clicked() doc->getDocument()->recompute(); qApp->restoreOverrideCursor(); - repairFoldsButton->setEnabled(false); - checkFoldsButton->setChecked(false); + d->ui.repairFoldsButton->setEnabled(false); + d->ui.checkFoldsButton->setChecked(false); removeViewProvider("MeshGui::ViewProviderMeshFolds"); } } @@ -1007,7 +1079,8 @@ void DlgEvaluateMeshImp::on_analyzeAllTogether_clicked() on_analyzeDegeneratedButton_clicked(); on_analyzeIndicesButton_clicked(); on_analyzeSelfIntersectionButton_clicked(); - on_analyzeFoldsButton_clicked(); + if (d->enableFoldsCheck) + on_analyzeFoldsButton_clicked(); } void DlgEvaluateMeshImp::on_repairAllTogether_clicked() @@ -1039,7 +1112,7 @@ void DlgEvaluateMeshImp::on_repairAllTogether_clicked() } qApp->processEvents(); } - { + if (d->enableFoldsCheck) { MeshEvalFoldsOnSurface s_eval(rMesh); MeshEvalFoldsOnBoundary b_eval(rMesh); MeshEvalFoldOversOnSurface f_eval(rMesh); @@ -1084,11 +1157,11 @@ void DlgEvaluateMeshImp::on_repairAllTogether_clicked() } } { - MeshEvalDegeneratedFacets eval(rMesh); + MeshEvalDegeneratedFacets eval(rMesh, d->epsilonDegenerated); if (!eval.Evaluate()) { Gui::Application::Instance->runCommand(true, - "App.getDocument(\"%s\").getObject(\"%s\").fixDegenerations()", - docName, objName); + "App.getDocument(\"%s\").getObject(\"%s\").fixDegenerations(%f)", + docName, objName, d->epsilonDegenerated); run = true; } qApp->processEvents(); @@ -1113,7 +1186,7 @@ void DlgEvaluateMeshImp::on_repairAllTogether_clicked() } qApp->processEvents(); } - } while(checkRepeatButton->isChecked() && run && (--max_iter > 0)); + } while(d->ui.checkRepeatButton->isChecked() && run && (--max_iter > 0)); } catch (const Base::Exception& e) { QMessageBox::warning(this, tr("Mesh repair"), QString::fromLatin1(e.what())); @@ -1127,13 +1200,43 @@ void DlgEvaluateMeshImp::on_repairAllTogether_clicked() } } +void DlgEvaluateMeshImp::on_buttonBox_clicked(QAbstractButton* button) +{ + QDialogButtonBox::StandardButton type = d->ui.buttonBox->standardButton(button); + if (type == QDialogButtonBox::Open) { + DlgEvaluateSettings dlg(this); + dlg.setNonmanifoldPointsChecked(d->checkNonManfoldPoints); + dlg.setFoldsChecked(d->enableFoldsCheck); + dlg.setDegenratedFacetsChecked(d->strictlyDegenerated); + if (dlg.exec() == QDialog::Accepted) { + d->checkNonManfoldPoints = dlg.isNonmanifoldPointsChecked(); + d->enableFoldsCheck = dlg.isFoldsChecked(); + d->showFoldsFunction(d->enableFoldsCheck); + d->strictlyDegenerated = dlg.isDegenratedFacetsChecked(); + if (d->strictlyDegenerated) + d->epsilonDegenerated = 0.0f; + else + d->epsilonDegenerated = MeshCore::MeshDefinitions::_fMinPointDistanceP2; + } + } + else if (type == QDialogButtonBox::Reset) { + removeViewProviders(); + cleanInformation(); + showInformation(); + d->self_intersections.clear(); + QList cbs = this->findChildren(); + Q_FOREACH (QCheckBox *cb, cbs) + cb->setChecked(false); + } +} + // ------------------------------------------------------------- -/* TRANSLATOR MeshGui::DockEvaluateMeshImp */ - -#if 0 // needed for Qt's lupdate utility - qApp->translate("QDockWidget", "Evaluate & Repair Mesh"); -#endif +/* TRANSLATOR MeshGui::DockEvaluateMeshImp */ + +#if 0 // needed for Qt's lupdate utility + qApp->translate("QDockWidget", "Evaluate & Repair Mesh"); +#endif DockEvaluateMeshImp* DockEvaluateMeshImp::_instance=0; @@ -1172,8 +1275,8 @@ DockEvaluateMeshImp::DockEvaluateMeshImp( QWidget* parent, Qt::WindowFlags fl ) // embed this dialog into a dockable widget container Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance(); // use Qt macro for preparing for translation stuff (but not translating yet) - QDockWidget* dw = pDockMgr->addDockWindow("Evaluate & Repair Mesh", - this, Qt::RightDockWidgetArea); + QDockWidget* dw = pDockMgr->addDockWindow("Evaluate & Repair Mesh", + this, Qt::RightDockWidgetArea); //dw->setAttribute(Qt::WA_DeleteOnClose); dw->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable); dw->show(); diff --git a/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.h b/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.h index db6b55105..ede8719b5 100644 --- a/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.h +++ b/src/Mod/Mesh/Gui/DlgEvaluateMeshImp.h @@ -30,7 +30,8 @@ #include #include #include -#include "ui_DlgEvaluateMesh.h" + +class QAbstractButton; namespace Gui { class View3DInventor; @@ -61,15 +62,15 @@ public Q_SLOTS: /** * \author Werner Mayer */ -class DlgEvaluateMeshImp : public QDialog, public Ui_DlgEvaluateMesh, public App::DocumentObserver +class DlgEvaluateMeshImp : public QDialog, public App::DocumentObserver { Q_OBJECT public: - DlgEvaluateMeshImp( QWidget* parent = 0, Qt::WindowFlags fl = 0 ); + DlgEvaluateMeshImp(QWidget* parent = 0, Qt::WindowFlags fl = 0); ~DlgEvaluateMeshImp(); - void setMesh( Mesh::Feature* ); + void setMesh(Mesh::Feature*); private: /** Checks if the given document is about to be closed */ @@ -119,6 +120,7 @@ protected Q_SLOTS: void on_refreshButton_clicked(); void on_meshNameButton_activated(int); + void on_buttonBox_clicked(QAbstractButton *); protected: void refreshList(); @@ -127,7 +129,7 @@ protected: void addViewProvider(const char* vp, const std::vector& indices); void removeViewProvider(const char* vp); void removeViewProviders(); - void changeEvent(QEvent *e); + void changeEvent(QEvent *e); private: class Private; diff --git a/src/Mod/Mesh/Gui/DlgEvaluateSettings.cpp b/src/Mod/Mesh/Gui/DlgEvaluateSettings.cpp new file mode 100644 index 000000000..c9aafae62 --- /dev/null +++ b/src/Mod/Mesh/Gui/DlgEvaluateSettings.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) 2016 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "DlgEvaluateSettings.h" +#include "ui_DlgEvaluateSettings.h" + +using namespace MeshGui; + +/* TRANSLATOR MeshGui::DlgEvaluateSettings */ + +DlgEvaluateSettings::DlgEvaluateSettings(QWidget* parent, Qt::WindowFlags fl) + : QDialog(parent, fl), ui(new Ui_DlgEvaluateSettings) +{ + ui->setupUi(this); +} + +DlgEvaluateSettings::~DlgEvaluateSettings() +{ + delete ui; +} + +void DlgEvaluateSettings::setNonmanifoldPointsChecked(bool on) +{ + ui->checkNonmanifoldPoints->setChecked(on); +} + +bool DlgEvaluateSettings::isNonmanifoldPointsChecked() const +{ + return ui->checkNonmanifoldPoints->isChecked(); +} + +void DlgEvaluateSettings::setFoldsChecked(bool on) +{ + ui->checkFolds->setChecked(on); +} + +bool DlgEvaluateSettings::isFoldsChecked() const +{ + return ui->checkFolds->isChecked(); +} + +void DlgEvaluateSettings::setDegenratedFacetsChecked(bool on) +{ + ui->checkDegenrated->setChecked(on); +} + +bool DlgEvaluateSettings::isDegenratedFacetsChecked() const +{ + return ui->checkDegenrated->isChecked(); +} + +#include "moc_DlgEvaluateSettings.cpp" + diff --git a/src/Mod/Mesh/Gui/DlgEvaluateSettings.h b/src/Mod/Mesh/Gui/DlgEvaluateSettings.h new file mode 100644 index 000000000..3b3be2fca --- /dev/null +++ b/src/Mod/Mesh/Gui/DlgEvaluateSettings.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (c) 2016 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ + + +#ifndef MESHGUI_DLG_EVALUATE_SETTINGS_H +#define MESHGUI_DLG_EVALUATE_SETTINGS_H + +#include + +namespace MeshGui { + +class Ui_DlgEvaluateSettings; + +/** + * \author Werner Mayer + */ +class DlgEvaluateSettings : public QDialog +{ + Q_OBJECT + +public: + DlgEvaluateSettings(QWidget* parent = 0, Qt::WindowFlags fl = 0); + ~DlgEvaluateSettings(); + + void setNonmanifoldPointsChecked(bool); + bool isNonmanifoldPointsChecked() const; + + void setFoldsChecked(bool); + bool isFoldsChecked() const; + + void setDegenratedFacetsChecked(bool); + bool isDegenratedFacetsChecked() const; + +private: + Ui_DlgEvaluateSettings* ui; +}; + +} // namespace MeshGui + +#endif // MESHGUI_DLG_EVALUATE_SETTINGS_H diff --git a/src/Mod/Mesh/Gui/DlgEvaluateSettings.ui b/src/Mod/Mesh/Gui/DlgEvaluateSettings.ui new file mode 100644 index 000000000..5e769417d --- /dev/null +++ b/src/Mod/Mesh/Gui/DlgEvaluateSettings.ui @@ -0,0 +1,110 @@ + + + MeshGui::DlgEvaluateSettings + + + + 0 + 0 + 344 + 149 + + + + Evaluation settings + + + + + + Settings + + + + + + Check for non-manifold points + + + + + + + Enable check for folds on surface + + + + + + + Consider a face only degenerated if it has no area + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + MeshGui::DlgEvaluateSettings + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + MeshGui::DlgEvaluateSettings + reject() + + + 316 + 260 + + + 286 + 274 + + + + +