From 9683abfc36c3e9e94b9175428ec9491b869a6b97 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 13 Dec 2018 17:31:21 +0100 Subject: [PATCH] improve mesh healing functions --- src/Mod/Mesh/App/Core/Degeneration.h | 10 +- src/Mod/Mesh/App/FacetPy.xml | 10 ++ src/Mod/Mesh/App/FacetPyImp.cpp | 19 +++ src/Mod/Mesh/App/FeatureMeshDefects.cpp | 6 +- src/Mod/Mesh/Gui/CMakeLists.txt | 9 ++ src/Mod/Mesh/Gui/ViewProvider.cpp | 9 ++ src/Mod/Mesh/Gui/ViewProvider.h | 2 + src/Mod/Mesh/Gui/ViewProviderMeshPy.xml | 42 +++++++ src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp | 137 +++++++++++++++++++++ 9 files changed, 237 insertions(+), 7 deletions(-) create mode 100644 src/Mod/Mesh/Gui/ViewProviderMeshPy.xml create mode 100644 src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp diff --git a/src/Mod/Mesh/App/Core/Degeneration.h b/src/Mod/Mesh/App/Core/Degeneration.h index dfd0112edb..1cbe696a4a 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.h +++ b/src/Mod/Mesh/App/Core/Degeneration.h @@ -362,8 +362,8 @@ public: std::vector GetIndices() const; private: - float fMinAngle; - float fMaxAngle; + float fMinAngle; /**< If an angle of a facet is lower than fMinAngle it's considered as deformed. */ + float fMaxAngle; /**< If an angle of a facet is higher than fMaxAngle it's considered as deformed. */ }; /** @@ -392,9 +392,9 @@ public: bool Fixup (); private: - float fMinAngle; - float fMaxAngle; - float fMaxSwapAngle; + float fMinAngle; /**< If an angle of a facet is lower than fMinAngle it's considered as deformed. */ + float fMaxAngle; /**< If an angle of a facet is higher than fMaxAngle it's considered as deformed. */ + float fMaxSwapAngle; /**< A swap edge is only allowed if the angle of both normals doesn't exceed fMaxSwapAngle */ float fEpsilon; }; diff --git a/src/Mod/Mesh/App/FacetPy.xml b/src/Mod/Mesh/App/FacetPy.xml index c5c35d04d8..113d723081 100644 --- a/src/Mod/Mesh/App/FacetPy.xml +++ b/src/Mod/Mesh/App/FacetPy.xml @@ -46,6 +46,16 @@ Returns true if the facet is degenerated, otherwise false. + + + isDegenerated(MinAngle, MaxAngle) -> boolean +Returns true if the facet is deformed, otherwise false. +A triangle is considered deformed if an angle is less than MinAngle +or higher than MaxAngle. +The two angles are given in radian. + + + The index of this facet in the MeshObject diff --git a/src/Mod/Mesh/App/FacetPyImp.cpp b/src/Mod/Mesh/App/FacetPyImp.cpp index f69eeb66f1..025772d9a0 100644 --- a/src/Mod/Mesh/App/FacetPyImp.cpp +++ b/src/Mod/Mesh/App/FacetPyImp.cpp @@ -146,6 +146,25 @@ PyObject* FacetPy::isDegenerated(PyObject *args) return Py::new_reference_to(Py::Boolean(tria.IsDegenerated(fEpsilon))); } +PyObject* FacetPy::isDeformed(PyObject *args) +{ + float fMinAngle; + float fMaxAngle; + if (!PyArg_ParseTuple(args, "ff", &fMinAngle, &fMaxAngle)) + return NULL; + + FacetPy::PointerType face = this->getFacetPtr(); + if (!face->isBound()) { + throw Py::RuntimeError("Unbound facet"); + } + + float fCosOfMinAngle = cos(fMinAngle); + float fCosOfMaxAngle = cos(fMaxAngle); + const MeshCore::MeshKernel& kernel = face->Mesh->getKernel(); + MeshCore::MeshGeomFacet tria = kernel.GetFacet(face->Index); + return Py::new_reference_to(Py::Boolean(tria.IsDeformed(fCosOfMinAngle, fCosOfMaxAngle))); +} + Py::List FacetPy::getPoints(void) const { FacetPy::PointerType face = this->getFacetPtr(); diff --git a/src/Mod/Mesh/App/FeatureMeshDefects.cpp b/src/Mod/Mesh/App/FeatureMeshDefects.cpp index f4d8e8e421..ddd53d44db 100644 --- a/src/Mod/Mesh/App/FeatureMeshDefects.cpp +++ b/src/Mod/Mesh/App/FeatureMeshDefects.cpp @@ -31,6 +31,7 @@ #include "Core/Degeneration.h" #include "Core/TopoAlgorithm.h" #include "Core/Triangulation.h" +#include using namespace Mesh; @@ -237,7 +238,7 @@ PROPERTY_SOURCE(Mesh::FixDeformations, Mesh::FixDefects) FixDeformations::FixDeformations() { - ADD_PROPERTY(MaxAngle ,(0.1f)); + ADD_PROPERTY(MaxAngle ,(5.0f)); } FixDeformations::~FixDeformations() @@ -253,7 +254,8 @@ App::DocumentObjectExecReturn *FixDeformations::execute(void) Mesh::PropertyMeshKernel* kernel = static_cast(prop); std::unique_ptr mesh(new MeshObject); *mesh = kernel->getValue(); - mesh->validateDeformations(static_cast(MaxAngle.getValue()), + float maxAngle = Base::toRadians(MaxAngle.getValue()); + mesh->validateDeformations(maxAngle, static_cast(Epsilon.getValue())); this->Mesh.setValuePtr(mesh.release()); } diff --git a/src/Mod/Mesh/Gui/CMakeLists.txt b/src/Mod/Mesh/Gui/CMakeLists.txt index 7786f60ba1..f5cd37612f 100644 --- a/src/Mod/Mesh/Gui/CMakeLists.txt +++ b/src/Mod/Mesh/Gui/CMakeLists.txt @@ -20,6 +20,13 @@ set(MeshGui_LIBS FreeCADGui ) +generate_from_xml(ViewProviderMeshPy) + +SET(MeshGui_XML_SRCS + ViewProviderMeshPy.xml +) +SOURCE_GROUP("XML" FILES ${MeshGui_XML_SRCS}) + set(Mesh_MOC_HDRS DlgEvaluateMeshImp.h DlgEvaluateSettings.h @@ -117,6 +124,7 @@ SET(ViewProvider_SRCS ViewProviderCurvature.h ViewProviderDefects.cpp ViewProviderDefects.h + ViewProviderMeshPyImp.cpp ViewProviderMeshFaceSet.cpp ViewProviderMeshFaceSet.h ViewProviderTransform.cpp @@ -127,6 +135,7 @@ SET(ViewProvider_SRCS SOURCE_GROUP("ViewProvider" FILES ${ViewProvider_SRCS}) SET(MeshGui_SRCS + ${MeshGui_XML_SRCS} ${Dialogs_SRCS} ${Inventor_SRCS} ${resource_SRCS} diff --git a/src/Mod/Mesh/Gui/ViewProvider.cpp b/src/Mod/Mesh/Gui/ViewProvider.cpp index d05a7d4d73..d7aac8927a 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.cpp +++ b/src/Mod/Mesh/Gui/ViewProvider.cpp @@ -93,6 +93,7 @@ #include #include #include +#include #include #include @@ -2046,6 +2047,14 @@ void ViewProviderMesh::highlightSegments(const std::vector& colors) } } +PyObject* ViewProviderMesh::getPyObject() +{ + if (!pyViewObject) + pyViewObject = new ViewProviderMeshPy(this); + pyViewObject->IncRef(); + return pyViewObject; +} + // ------------------------------------------------------ PROPERTY_SOURCE(MeshGui::ViewProviderIndexedFaceSet, MeshGui::ViewProviderMesh) diff --git a/src/Mod/Mesh/Gui/ViewProvider.h b/src/Mod/Mesh/Gui/ViewProvider.h index 4820eaf98f..b1a374c338 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.h +++ b/src/Mod/Mesh/Gui/ViewProvider.h @@ -136,6 +136,8 @@ public: bool exportToVrml(const char* filename, const MeshCore::Material&, bool binary=false) const; void exportMesh(const char* filename, const char* fmt=0) const; void setupContextMenu(QMenu*, QObject*, const char*); + /// Get the python wrapper for that ViewProvider + PyObject* getPyObject(); /** @name Editing */ //@{ diff --git a/src/Mod/Mesh/Gui/ViewProviderMeshPy.xml b/src/Mod/Mesh/Gui/ViewProviderMeshPy.xml new file mode 100644 index 0000000000..1dc409c969 --- /dev/null +++ b/src/Mod/Mesh/Gui/ViewProviderMeshPy.xml @@ -0,0 +1,42 @@ + + + + + + This is the ViewProvider base class + + + + Select list of facets + + + + + Add list of facets to selection + + + + + Remove list of facets from selection + + + + + Invert the selection + + + + + Clear the selection + + + + diff --git a/src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp b/src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp new file mode 100644 index 0000000000..a8215fa589 --- /dev/null +++ b/src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (c) 2018 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_ +# include +#endif + +#include + +// inclusion of the generated files (generated out of ViewProviderMeshPy.xml) +#include "ViewProviderMeshPy.h" +#include "ViewProviderMeshPy.cpp" + +using namespace MeshGui; + +// returns a string which represents the object e.g. when printed in python +std::string ViewProviderMeshPy::representation(void) const +{ + std::stringstream str; + str << ""; + + return str.str(); +} + +PyObject* ViewProviderMeshPy::setSelection(PyObject *args) +{ + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)) + return 0; + + Py::Sequence list(obj); + std::vector selection; + selection.reserve(list.size()); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + Py::Long index(*it); + unsigned long value = static_cast(index); + selection.push_back(value); + } + + ViewProviderMesh* vp = getViewProviderMeshPtr(); + vp->setSelection(selection); + Py_Return; +} + +PyObject* ViewProviderMeshPy::addSelection(PyObject *args) +{ + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)) + return 0; + + Py::Sequence list(obj); + std::vector selection; + selection.reserve(list.size()); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + Py::Long index(*it); + unsigned long value = static_cast(index); + selection.push_back(value); + } + + ViewProviderMesh* vp = getViewProviderMeshPtr(); + vp->addSelection(selection); + Py_Return; +} + +PyObject* ViewProviderMeshPy::removeSelection(PyObject *args) +{ + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)) + return 0; + + Py::Sequence list(obj); + std::vector selection; + selection.reserve(list.size()); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + Py::Long index(*it); + unsigned long value = static_cast(index); + selection.push_back(value); + } + + ViewProviderMesh* vp = getViewProviderMeshPtr(); + vp->removeSelection(selection); + Py_Return; +} + +PyObject* ViewProviderMeshPy::invertSelection(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + + ViewProviderMesh* vp = getViewProviderMeshPtr(); + vp->invertSelection(); + Py_Return; +} + +PyObject* ViewProviderMeshPy::clearSelection(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + + ViewProviderMesh* vp = getViewProviderMeshPtr(); + vp->clearSelection(); + Py_Return; +} + + + +PyObject *ViewProviderMeshPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int ViewProviderMeshPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +}