Part: expose ShapeFix and ShapeFix_Face to Python

This commit is contained in:
wmayer
2022-05-01 12:15:09 +02:00
parent f3e941a382
commit b6cd635cc1
7 changed files with 741 additions and 1 deletions

View File

@@ -101,6 +101,7 @@
#include <Mod/Part/App/PrecisionPy.h>
#include <Mod/Part/App/RectangularTrimmedSurfacePy.h>
#include <Mod/Part/App/ShapeFix/ShapeFix_RootPy.h>
#include <Mod/Part/App/ShapeFix/ShapeFix_FacePy.h>
#include <Mod/Part/App/ShapeFix/ShapeFix_ShellPy.h>
#include <Mod/Part/App/ShapeUpgrade/UnifySameDomainPy.h>
#include "Mod/Part/App/SpherePy.h"
@@ -342,6 +343,7 @@ PyMOD_INIT_FUNC(Part)
// ShapeFix sub-module
PyObject* shapeFix(module.getAttr("ShapeFix").ptr());
Base::Interpreter().addType(&Part::ShapeFix_RootPy::Type, shapeFix, "Root");
Base::Interpreter().addType(&Part::ShapeFix_FacePy::Type, shapeFix, "Face");
Base::Interpreter().addType(&Part::ShapeFix_ShellPy::Type, shapeFix, "Shell");
// ShapeUpgrade sub-module

View File

@@ -58,6 +58,8 @@
# include <Interface_Static.hxx>
# include <NCollection_List.hxx>
# include <Precision.hxx>
# include <ShapeFix.hxx>
# include <ShapeBuild_ReShape.hxx>
# include <ShapeUpgrade_ShellSewing.hxx>
# include <Standard_ConstructionError.hxx>
# include <Standard_DomainError.hxx>
@@ -308,10 +310,87 @@ class ShapeFixModule : public Py::ExtensionModule<ShapeFixModule>
public:
ShapeFixModule() : Py::ExtensionModule<ShapeFixModule>("ShapeFix")
{
add_varargs_method("sameParameter",&ShapeFixModule::sameParameter,
"sameParameter(shape, enforce, prec=0.0)"
);
add_varargs_method("encodeRegularity",&ShapeFixModule::encodeRegularity,
"encodeRegularity(shape, tolerance = 1e-10)\n"
);
add_varargs_method("removeSmallEdges",&ShapeFixModule::removeSmallEdges,
"removeSmallEdges(shape, tolerance, ReShapeContext)\n"
"Removes edges which are less than given tolerance from shape"
);
add_varargs_method("fixVertexPosition",&ShapeFixModule::fixVertexPosition,
"fixVertexPosition(shape, tolerance, ReShapeContext)\n"
"Fix position of the vertices having tolerance more tnan specified one"
);
add_varargs_method("leastEdgeSize",&ShapeFixModule::leastEdgeSize,
"leastEdgeSize(shape)\n"
"Calculate size of least edge"
);
initialize("This is a module working with the ShapeFix framework."); // register with Python
}
virtual ~ShapeFixModule() {}
private:
Py::Object sameParameter(const Py::Tuple& args)
{
PyObject* shape;
PyObject* enforce;
double prec = 0.0;
if (!PyArg_ParseTuple(args.ptr(), "O!O!|d", &TopoShapePy::Type, &shape, &PyBool_Type, &enforce, &prec))
throw Py::Exception();
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
bool ok = ShapeFix::SameParameter(sh, PyObject_IsTrue(enforce) ? Standard_True : Standard_False, prec);
return Py::Boolean(ok);
}
Py::Object encodeRegularity(const Py::Tuple& args)
{
PyObject* shape;
double tolang = 1.0e-10;
if (!PyArg_ParseTuple(args.ptr(), "O!|d", &TopoShapePy::Type, &shape, &tolang))
throw Py::Exception();
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
ShapeFix::EncodeRegularity(sh, tolang);
return Py::None();
}
Py::Object removeSmallEdges(const Py::Tuple& args)
{
PyObject* shape;
double tol;
if (!PyArg_ParseTuple(args.ptr(), "O!d", &TopoShapePy::Type, &shape, &tol))
throw Py::Exception();
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
Handle(ShapeBuild_ReShape) reshape = new ShapeBuild_ReShape();
TopoShape res = ShapeFix::RemoveSmallEdges(sh, tol, reshape);
return Py::asObject(res.getPyObject());
}
Py::Object fixVertexPosition(const Py::Tuple& args)
{
PyObject* shape;
double tol;
if (!PyArg_ParseTuple(args.ptr(), "O!d", &TopoShapePy::Type, &shape, &tol))
throw Py::Exception();
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
Handle(ShapeBuild_ReShape) reshape = new ShapeBuild_ReShape();
bool ok = ShapeFix::FixVertexPosition(sh, tol, reshape);
return Py::Boolean(ok);
}
Py::Object leastEdgeSize(const Py::Tuple& args)
{
PyObject* shape;
if (!PyArg_ParseTuple(args.ptr(), "O!", &TopoShapePy::Type, &shape))
throw Py::Exception();
TopoDS_Shape sh = static_cast<TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
double len = ShapeFix::LeastEdgeSize(sh);
return Py::Float(len);
}
};
class ShapeUpgradeModule : public Py::ExtensionModule<ShapeUpgradeModule>

View File

@@ -137,6 +137,7 @@ generate_from_xml(HLRBRep/HLRBRep_PolyAlgoPy)
generate_from_xml(HLRBRep/PolyHLRToShapePy)
generate_from_xml(ShapeFix/ShapeFix_RootPy)
generate_from_xml(ShapeFix/ShapeFix_FacePy)
generate_from_xml(ShapeFix/ShapeFix_ShellPy)
generate_from_xml(ShapeUpgrade/UnifySameDomainPy)
@@ -425,6 +426,8 @@ SOURCE_GROUP("HLRBRep" FILES ${HLRBRepPy_SRCS})
SET(ShapeFixPy_SRCS
ShapeFix/ShapeFix_RootPy.xml
ShapeFix/ShapeFix_RootPyImp.cpp
ShapeFix/ShapeFix_FacePy.xml
ShapeFix/ShapeFix_FacePyImp.cpp
ShapeFix/ShapeFix_ShellPy.xml
ShapeFix/ShapeFix_ShellPyImp.cpp
)

View File

@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="ShapeFix_RootPy"
Name="ShapeFix_FacePy"
PythonName="Part.ShapeFix.Face"
Twin="ShapeFix_Face"
TwinPointer="ShapeFix_Face"
Include="ShapeFix_Face.hxx"
Namespace="Part"
FatherInclude="Mod/Part/App/ShapeFix/ShapeFix_RootPy.h"
FatherNamespace="Part"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Werner Mayer" EMail="wmayer@users.sourceforge.net" />
<UserDocu>Class for fixing operations on faces</UserDocu>
</Documentation>
<Methode Name="init">
<Documentation>
<UserDocu>Initializes by face</UserDocu>
</Documentation>
</Methode>
<Methode Name="clearModes">
<Documentation>
<UserDocu>Iterates on subshapes and performs fixes</UserDocu>
</Documentation>
</Methode>
<Methode Name="add">
<Documentation>
<UserDocu>Add a wire to current face using BRep_Builder.
Wire is added without taking into account orientation of face
(as if face were FORWARD)
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixOrientation">
<Documentation>
<UserDocu>
Fixes orientation of wires on the face
It tries to make all wires lie outside all others (according
to orientation) by reversing orientation of some of them.
If face lying on sphere or torus has single wire and
AddNaturalBoundMode is True, that wire is not reversed in
any case (supposing that natural bound will be added).
Returns True if wires were reversed
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixAddNaturalBound">
<Documentation>
<UserDocu>
Adds natural boundary on face if it is missing.
Two cases are supported:
- face has no wires
- face lies on geometrically double-closed surface
(sphere or torus) and none of wires is left-oriented
Returns True if natural boundary was added
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixMissingSeam">
<Documentation>
<UserDocu>
Detects and fixes the special case when face on a closed
surface is given by two wires closed in 3d but with gap in 2d.
In that case it creates a new wire from the two, and adds a
missing seam edge
Returns True if missing seam was added
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixSmallAreaWire">
<Documentation>
<UserDocu>
Detects wires with small area (that is less than
100*Precision.PConfusion(). Removes these wires if they are internal.
Returns True if at least one small wire removed, False nothing is done.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixLoopWire">
<Documentation>
<UserDocu>
Detects if wire has a loop and fixes this situation by splitting on the few parts.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixIntersectingWires">
<Documentation>
<UserDocu>
Detects and fixes the special case when face has more than one wire
and this wires have intersection point
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixWiresTwoCoincidentEdges">
<Documentation>
<UserDocu>
If wire contains two coincidence edges it must be removed
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fixPeriodicDegenerated">
<Documentation>
<UserDocu>
Fixes topology for a specific case when face is composed
by a single wire belting a periodic surface. In that case
a degenerated edge is reconstructed in the degenerated pole
of the surface. Initial wire gets consistent orientation.
Must be used in couple and before FixMissingSeam routine
</UserDocu>
</Documentation>
</Methode>
<Methode Name="perform">
<Documentation>
<UserDocu>Iterates on subshapes and performs fixes</UserDocu>
</Documentation>
</Methode>
<Methode Name="face">
<Documentation>
<UserDocu>Returns a face which corresponds to the current state</UserDocu>
</Documentation>
</Methode>
<Methode Name="result">
<Documentation>
<UserDocu>Returns resulting shape (Face or Shell if splitted)
To be used instead of face() if FixMissingSeam involved
</UserDocu>
</Documentation>
</Methode>
<Attribute Name="FixWireMode" ReadOnly="false">
<Documentation>
<UserDocu>Mode for applying fixes of ShapeFix_Wire</UserDocu>
</Documentation>
<Parameter Name="FixWireMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixOrientationMode" ReadOnly="false">
<Documentation>
<UserDocu>Mode for applying fixes of orientation
If True, wires oriented to border limited square
</UserDocu>
</Documentation>
<Parameter Name="FixOrientationMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixAddNaturalBoundMode" ReadOnly="false">
<Documentation>
<UserDocu>If true, natural boundary is added on faces that miss them.
Default is False for faces with single wire (they are
handled by FixOrientation in that case) and True for others.
</UserDocu>
</Documentation>
<Parameter Name="FixAddNaturalBoundMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixMissingSeamMode" ReadOnly="false">
<Documentation>
<UserDocu>If True, tries to insert seam if missing</UserDocu>
</Documentation>
<Parameter Name="FixMissingSeamMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixSmallAreaWireMode" ReadOnly="false">
<Documentation>
<UserDocu>If True, drops small wires</UserDocu>
</Documentation>
<Parameter Name="FixSmallAreaWireMode" Type="Boolean"/>
</Attribute>
<Attribute Name="RemoveSmallAreaFaceMode" ReadOnly="false">
<Documentation>
<UserDocu>If True, drops small wires</UserDocu>
</Documentation>
<Parameter Name="RemoveSmallAreaFaceMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixIntersectingWiresMode" ReadOnly="false">
<Documentation>
<UserDocu>Mode for applying fixes of intersecting wires</UserDocu>
</Documentation>
<Parameter Name="FixIntersectingWiresMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixLoopWiresMode" ReadOnly="false">
<Documentation>
<UserDocu>Mode for applying fixes of loop wires</UserDocu>
</Documentation>
<Parameter Name="FixLoopWiresMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixSplitFaceMode" ReadOnly="false">
<Documentation>
<UserDocu>Mode for applying fixes of split face</UserDocu>
</Documentation>
<Parameter Name="FixSplitFaceMode" Type="Boolean"/>
</Attribute>
<Attribute Name="AutoCorrectPrecisionMode" ReadOnly="false">
<Documentation>
<UserDocu>Mode for applying auto-corrected precision</UserDocu>
</Documentation>
<Parameter Name="AutoCorrectPrecisionMode" Type="Boolean"/>
</Attribute>
<Attribute Name="FixPeriodicDegeneratedMode" ReadOnly="false">
<Documentation>
<UserDocu>Mode for applying periodic degeneration</UserDocu>
</Documentation>
<Parameter Name="FixPeriodicDegeneratedMode" Type="Boolean"/>
</Attribute>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,354 @@
/***************************************************************************
* Copyright (c) 2022 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 <TopoDS.hxx>
#endif
#include "ShapeFix/ShapeFix_FacePy.h"
#include "ShapeFix/ShapeFix_FacePy.cpp"
#include <Mod/Part/App/GeometrySurfacePy.h>
#include <Mod/Part/App/TopoShapeFacePy.h>
#include <Mod/Part/App/TopoShapeWirePy.h>
using namespace Part;
// returns a string which represents the object e.g. when printed in python
std::string ShapeFix_FacePy::representation() const
{
return "<ShapeFix_Face object>";
}
PyObject *ShapeFix_FacePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
{
// create a new instance of ShapeFix_FacePy
return new ShapeFix_FacePy(new ShapeFix_Face);
}
// constructor method
int ShapeFix_FacePy::PyInit(PyObject* args, PyObject* /*kwds*/)
{
PyObject* face = nullptr;
if (PyArg_ParseTuple(args, "|O!", &TopoShapeFacePy::Type, &face)) {
if (face) {
getShapeFix_FacePtr()->Init(TopoDS::Face(static_cast<TopoShapePy*>(face)->getTopoShapePtr()->getShape()));
}
return 0;
}
PyErr_Clear();
double prec;
PyObject* fwd = Py_True;
if (PyArg_ParseTuple(args, "O!d|O!", &GeometrySurfacePy::Type, &face, &prec, &PyBool_Type, &fwd)) {
if (face) {
Handle(Geom_Surface) surf = Handle(Geom_Surface)::DownCast(static_cast<GeometrySurfacePy*>(face)->getGeomSurfacePtr()->handle());
getShapeFix_FacePtr()->Init(surf, prec, PyObject_IsTrue(fwd) ? Standard_True : Standard_False);
}
return 0;
}
PyErr_SetString(PyExc_TypeError, "Supported arguments are:\n"
"-- Face\n"
"-- Surface, Precision, [Forward=True}\n"
" Precision is a Float\n"
" If Forward is the orientation will be FORWARD or REVERSED otherwise"
);
return -1;
}
PyObject* ShapeFix_FacePy::init(PyObject *args)
{
PyObject* face;
if (PyArg_ParseTuple(args, "O!", &TopoShapeFacePy::Type, &face)) {
getShapeFix_FacePtr()->Init(TopoDS::Face(static_cast<TopoShapePy*>(face)->getTopoShapePtr()->getShape()));
Py_Return;
}
PyErr_Clear();
double prec;
PyObject* fwd = Py_True;
if (PyArg_ParseTuple(args, "O!d|O!", &GeometrySurfacePy::Type, &face, &prec, &PyBool_Type, &fwd)) {
if (face) {
Handle(Geom_Surface) surf = Handle(Geom_Surface)::DownCast(static_cast<GeometrySurfacePy*>(face)->getGeomSurfacePtr()->handle());
getShapeFix_FacePtr()->Init(surf, prec, PyObject_IsTrue(fwd) ? Standard_True : Standard_False);
}
Py_Return;
}
PyErr_SetString(PyExc_TypeError, "Supported arguments are:\n"
"-- Face\n"
"-- Surface, Precision, [Forward=True}\n"
" Precision is a Float\n"
" If Forward is the orientation will be FORWARD or REVERSED otherwise"
);
return nullptr;
}
PyObject* ShapeFix_FacePy::clearModes(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
getShapeFix_FacePtr()->ClearModes();
Py_Return;
}
PyObject* ShapeFix_FacePy::add(PyObject *args)
{
PyObject* wire;
if (!PyArg_ParseTuple(args, "O!", &TopoShapeWirePy::Type, &wire))
return nullptr;
getShapeFix_FacePtr()->Add(TopoDS::Wire(static_cast<TopoShapePy*>(wire)->getTopoShapePtr()->getShape()));
Py_Return;
}
PyObject* ShapeFix_FacePy::fixOrientation(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->FixOrientation();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::fixAddNaturalBound(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->FixAddNaturalBound();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::fixMissingSeam(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->FixMissingSeam();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::fixSmallAreaWire(PyObject *args)
{
PyObject* removeSmall;
if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &removeSmall))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->FixSmallAreaWire(PyObject_IsTrue(removeSmall) ? Standard_True : Standard_False);
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::fixLoopWire(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
TopTools_SequenceOfShape aResWires;
Standard_Boolean ok = getShapeFix_FacePtr()->FixLoopWire(aResWires);
Py::List list;
for (int index = aResWires.Lower(); index <= aResWires.Upper(); index++) {
TopoShape sh = aResWires(index);
list.append(Py::asObject(sh.getPyObject()));
}
return Py::new_reference_to(Py::TupleN(Py::Boolean(ok), list));
}
PyObject* ShapeFix_FacePy::fixIntersectingWires(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->FixIntersectingWires();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::fixWiresTwoCoincidentEdges(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->FixWiresTwoCoincEdges();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::fixPeriodicDegenerated(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->FixPeriodicDegenerated();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::perform(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
Standard_Boolean ok = getShapeFix_FacePtr()->Perform();
return Py::new_reference_to(Py::Boolean(ok));
}
PyObject* ShapeFix_FacePy::face(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
TopoShape shape = getShapeFix_FacePtr()->Face();
return shape.getPyObject();
}
PyObject* ShapeFix_FacePy::result(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
TopoShape shape = getShapeFix_FacePtr()->Result();
return shape.getPyObject();
}
Py::Boolean ShapeFix_FacePy::getFixWireMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixWireMode());
}
void ShapeFix_FacePy::setFixWireMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixWireMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixOrientationMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixOrientationMode());
}
void ShapeFix_FacePy::setFixOrientationMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixOrientationMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixAddNaturalBoundMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixAddNaturalBoundMode());
}
void ShapeFix_FacePy::setFixAddNaturalBoundMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixAddNaturalBoundMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixMissingSeamMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixMissingSeamMode());
}
void ShapeFix_FacePy::setFixMissingSeamMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixMissingSeamMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixSmallAreaWireMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixSmallAreaWireMode());
}
void ShapeFix_FacePy::setFixSmallAreaWireMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixSmallAreaWireMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getRemoveSmallAreaFaceMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->RemoveSmallAreaFaceMode());
}
void ShapeFix_FacePy::setRemoveSmallAreaFaceMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->RemoveSmallAreaFaceMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixIntersectingWiresMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixIntersectingWiresMode());
}
void ShapeFix_FacePy::setFixIntersectingWiresMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixIntersectingWiresMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixLoopWiresMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixLoopWiresMode());
}
void ShapeFix_FacePy::setFixLoopWiresMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixLoopWiresMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixSplitFaceMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixSplitFaceMode());
}
void ShapeFix_FacePy::setFixSplitFaceMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixSplitFaceMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getAutoCorrectPrecisionMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->AutoCorrectPrecisionMode());
}
void ShapeFix_FacePy::setAutoCorrectPrecisionMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->AutoCorrectPrecisionMode() = arg;
}
Py::Boolean ShapeFix_FacePy::getFixPeriodicDegeneratedMode() const
{
return Py::Boolean(getShapeFix_FacePtr()->FixPeriodicDegeneratedMode());
}
void ShapeFix_FacePy::setFixPeriodicDegeneratedMode(Py::Boolean arg)
{
getShapeFix_FacePtr()->FixPeriodicDegeneratedMode() = arg;
}
PyObject *ShapeFix_FacePy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int ShapeFix_FacePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -45,8 +45,11 @@ PyObject *ShapeFix_RootPy::PyMake(struct _typeobject *, PyObject *, PyObject *)
}
// constructor method
int ShapeFix_RootPy::PyInit(PyObject* /*args*/, PyObject* /*kwds*/)
int ShapeFix_RootPy::PyInit(PyObject* args, PyObject* /*kwds*/)
{
if (!PyArg_ParseTuple(args, ""))
return -1;
return 0;
}

View File

@@ -394,3 +394,99 @@ class PartTestRuledSurface(unittest.TestCase):
def tearDown(self):
FreeCAD.closeDocument(self.Doc.Name)
class PartTestShapeFix(unittest.TestCase):
def testShapeFix_Root(self):
with self.assertRaises(TypeError):
Part.ShapeFix.Root([])
fix = Part.ShapeFix.Root()
print (fix)
fix.Precision = 0.0
self.assertEqual(fix.Precision, 0.0)
fix.MinTolerance = 0.0
self.assertEqual(fix.MinTolerance, 0.0)
fix.MaxTolerance = 0.5
self.assertEqual(fix.MaxTolerance, 0.5)
self.assertEqual(fix.limitTolerance(0.25), 0.25)
def testShapeFix_Face(self):
surface = Part.Plane()
face = surface.toShape(-1, 1, -1, 1)
Part.ShapeFix.Face()
Part.ShapeFix.Face(surface, 0.00001, True)
with self.assertRaises(TypeError):
Part.ShapeFix.Face([])
fix = Part.ShapeFix.Face(face)
print (fix)
fix.fixOrientation()
fix.fixAddNaturalBound()
fix.fixMissingSeam()
fix.fixSmallAreaWire(True)
fix.fixLoopWire()
fix.fixIntersectingWires()
fix.fixWiresTwoCoincidentEdges()
fix.fixPeriodicDegenerated()
fix.perform()
fix.add(face.OuterWire)
current = fix.face()
result = fix.result()
fix.FixWireMode = True
self.assertEqual(fix.FixWireMode, True)
fix.FixOrientationMode = True
self.assertEqual(fix.FixOrientationMode, True)
fix.FixAddNaturalBoundMode = True
self.assertEqual(fix.FixAddNaturalBoundMode, True)
fix.FixMissingSeamMode = True
self.assertEqual(fix.FixMissingSeamMode, True)
fix.FixSmallAreaWireMode = True
self.assertEqual(fix.FixSmallAreaWireMode, True)
fix.RemoveSmallAreaFaceMode = True
self.assertEqual(fix.RemoveSmallAreaFaceMode, True)
fix.FixIntersectingWiresMode = True
self.assertEqual(fix.FixIntersectingWiresMode, True)
fix.FixLoopWiresMode = True
self.assertEqual(fix.FixLoopWiresMode, True)
fix.FixSplitFaceMode = True
self.assertEqual(fix.FixSplitFaceMode, True)
fix.AutoCorrectPrecisionMode = True
self.assertEqual(fix.AutoCorrectPrecisionMode, True)
fix.FixPeriodicDegeneratedMode = True
self.assertEqual(fix.FixPeriodicDegeneratedMode, True)
fix.clearModes()
def testShapeFix_Shell(self):
surface = Part.Plane()
face = surface.toShape(-1, 1, -1, 1)
shell = Part.Shell([face])
Part.ShapeFix.Shell()
with self.assertRaises(TypeError):
Part.ShapeFix.Face([])
fix = Part.ShapeFix.Shell(shell)
fix.init(shell)
print (fix)
fix.perform()
fix.shell()
fix.shape()