improve mesh healing functions

This commit is contained in:
wmayer
2018-12-13 17:31:21 +01:00
parent 3b2c3b1d99
commit 9683abfc36
9 changed files with 237 additions and 7 deletions

View File

@@ -362,8 +362,8 @@ public:
std::vector<unsigned long> 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;
};

View File

@@ -46,6 +46,16 @@ Returns true if the facet is degenerated, otherwise false.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="isDeformed">
<Documentation>
<UserDocu>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.
</UserDocu>
</Documentation>
</Methode>
<Attribute Name="Index" ReadOnly="true">
<Documentation>
<UserDocu>The index of this facet in the MeshObject</UserDocu>

View File

@@ -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();

View File

@@ -31,6 +31,7 @@
#include "Core/Degeneration.h"
#include "Core/TopoAlgorithm.h"
#include "Core/Triangulation.h"
#include <Base/Tools.h>
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<Mesh::PropertyMeshKernel*>(prop);
std::unique_ptr<MeshObject> mesh(new MeshObject);
*mesh = kernel->getValue();
mesh->validateDeformations(static_cast<float>(MaxAngle.getValue()),
float maxAngle = Base::toRadians(MaxAngle.getValue());
mesh->validateDeformations(maxAngle,
static_cast<float>(Epsilon.getValue()));
this->Mesh.setValuePtr(mesh.release());
}

View File

@@ -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}

View File

@@ -93,6 +93,7 @@
#include <Mod/Mesh/App/Core/Visitor.h>
#include <Mod/Mesh/App/Mesh.h>
#include <Mod/Mesh/App/MeshFeature.h>
#include <Mod/Mesh/Gui/ViewProviderMeshPy.h>
#include <zipios++/gzipoutputstream.h>
#include <boost/bind.hpp>
@@ -2046,6 +2047,14 @@ void ViewProviderMesh::highlightSegments(const std::vector<App::Color>& colors)
}
}
PyObject* ViewProviderMesh::getPyObject()
{
if (!pyViewObject)
pyViewObject = new ViewProviderMeshPy(this);
pyViewObject->IncRef();
return pyViewObject;
}
// ------------------------------------------------------
PROPERTY_SOURCE(MeshGui::ViewProviderIndexedFaceSet, MeshGui::ViewProviderMesh)

View File

@@ -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 */
//@{

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="ViewProviderDocumentObjectPy"
Name="ViewProviderMeshPy"
Twin="ViewProviderMesh"
TwinPointer="ViewProviderMesh"
Include="Mod/Mesh/Gui/ViewProvider.h"
Namespace="MeshGui"
FatherInclude="Gui/ViewProviderDocumentObjectPy.h"
FatherNamespace="Gui">
<Documentation>
<Author Licence="LGPL" Name="Werner Mayer" EMail="wmayer@users.sourceforge.net" />
<UserDocu>This is the ViewProvider base class</UserDocu>
</Documentation>
<Methode Name="setSelection">
<Documentation>
<UserDocu>Select list of facets</UserDocu>
</Documentation>
</Methode>
<Methode Name="addSelection">
<Documentation>
<UserDocu>Add list of facets to selection</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeSelection">
<Documentation>
<UserDocu>Remove list of facets from selection</UserDocu>
</Documentation>
</Methode>
<Methode Name="invertSelection">
<Documentation>
<UserDocu>Invert the selection</UserDocu>
</Documentation>
</Methode>
<Methode Name="clearSelection">
<Documentation>
<UserDocu>Clear the selection</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,137 @@
/***************************************************************************
* Copyright (c) 2018 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <sstream>
#endif
#include <Mod/Mesh/Gui/ViewProvider.h>
// 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 << "<View provider object at " << getViewProviderDocumentObjectPtr() << ">";
return str.str();
}
PyObject* ViewProviderMeshPy::setSelection(PyObject *args)
{
PyObject* obj;
if (!PyArg_ParseTuple(args, "O", &obj))
return 0;
Py::Sequence list(obj);
std::vector<unsigned long> 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<unsigned long>(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<unsigned long> 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<unsigned long>(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<unsigned long> 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<unsigned long>(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;
}