diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 31eaa25a27..5f0163af5e 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -124,6 +124,9 @@ #include #include #include +#include +#include +#include #include "PropertyGeometryList.h" #include "DatumFeature.h" #include "Attacher.h" @@ -416,6 +419,12 @@ PyMOD_INIT_FUNC(Part) Base::Interpreter().addType(&Part::Line2dPy::Type,geom2dModule,"Line2d"); Base::Interpreter().addType(&Part::OffsetCurve2dPy::Type,geom2dModule,"OffsetCurve2d"); + // GeomPlate sub-module + PyObject* geomPlate(module.getAttr("GeomPlate").ptr()); + Base::Interpreter().addType(&Part::BuildPlateSurfacePy::Type, geomPlate, "BuildPlateSurface"); + Base::Interpreter().addType(&Part::CurveConstraintPy::Type, geomPlate, "CurveConstraint"); + Base::Interpreter().addType(&Part::PointConstraintPy::Type, geomPlate, "PointConstraint"); + Part::TopoShape ::init(); Part::PropertyPartShape ::init(); Part::PropertyGeometryList ::init(); diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 60d732176d..c8242dcdef 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -271,8 +271,20 @@ PartExport std::list sort_Edges(double tol3d, std::list +{ +public: + GeomPlateModule() : Py::ExtensionModule("GeomPlate") + { + initialize("This is a module working with the GeomPlate framework."); // register with Python + } + + virtual ~GeomPlateModule() {} +}; + class Module : public Py::ExtensionModule { + GeomPlateModule geomPlate; public: Module() : Py::ExtensionModule("Part") { @@ -488,6 +500,8 @@ public: "joinSubname(sub,mapped,subElement) -> subname\n" ); initialize("This is a module working with shapes."); // register with Python + + PyModule_AddObject(m_module, "GeomPlate", geomPlate.module().ptr()); } virtual ~Module() {} diff --git a/src/Mod/Part/App/CMakeLists.txt b/src/Mod/Part/App/CMakeLists.txt index 21d63cf558..e96c676bba 100644 --- a/src/Mod/Part/App/CMakeLists.txt +++ b/src/Mod/Part/App/CMakeLists.txt @@ -94,6 +94,7 @@ generate_from_xml(BRepOffsetAPI_MakePipeShellPy) # make sure to create the directory at configure time file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Geom2d) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/GeomPlate) generate_from_xml(Geom2d/ArcOfCircle2dPy) generate_from_xml(Geom2d/ArcOfConic2dPy) @@ -113,6 +114,10 @@ generate_from_xml(Geom2d/Line2dPy) generate_from_xml(Geom2d/OffsetCurve2dPy) generate_from_xml(Geom2d/Parabola2dPy) +generate_from_xml(GeomPlate/BuildPlateSurfacePy) +generate_from_xml(GeomPlate/CurveConstraintPy) +generate_from_xml(GeomPlate/PointConstraintPy) + SET(Features_SRCS FeaturePartBoolean.cpp FeaturePartBoolean.h @@ -341,11 +346,24 @@ SET(Geom2dPy_SRCS SOURCE_GROUP("Geom2d" FILES ${Geom2dPy_SRCS}) +# GeomPlate wrappers +SET(GeomPlatePy_SRCS + GeomPlate/BuildPlateSurfacePy.xml + GeomPlate/BuildPlateSurfacePyImp.cpp + GeomPlate/CurveConstraintPy.xml + GeomPlate/CurveConstraintPyImp.cpp + GeomPlate/PointConstraintPy.xml + GeomPlate/PointConstraintPyImp.cpp +) + +SOURCE_GROUP("GeomPlate" FILES ${GeomPlatePy_SRCS}) + SET(Part_SRCS ${Features_SRCS} ${Properties_SRCS} ${Python_SRCS} ${Geom2dPy_SRCS} + ${GeomPlatePy_SRCS} Attacher.cpp Attacher.h AppPart.cpp diff --git a/src/Mod/Part/App/GeomPlate/BuildPlateSurfacePy.xml b/src/Mod/Part/App/GeomPlate/BuildPlateSurfacePy.xml new file mode 100644 index 0000000000..4016dc8495 --- /dev/null +++ b/src/Mod/Part/App/GeomPlate/BuildPlateSurfacePy.xml @@ -0,0 +1,112 @@ + + + + + + This class provides an algorithm for constructing such a plate surface. + + + + Resets all constraints + + + + + + + + + + Loads the initial surface + + + + + Returns the initial surface + + + + + Returns the plate surface + + + + + Adds a linear or point constraint + + + + + Calls the algorithm and computes the plate surface + + + + + Tests whether computation of the plate has been completed + + + + + Returns the orientation of the curves in the the array returned by curves2d + + + + + Returns the order of the curves in the array returned by curves2d + + + + + Extracts the array of curves on the plate surface which + correspond to the curve constraints set in add() + + + + + + Returns the curve constraint of order + + + + + Returns the point constraint of order + + + + + + + + + + + + + + + Returns the max distance betwen the result and the constraints + + + + + Returns the max angle betwen the result and the constraints + + + + + Returns the max difference of curvature betwen the result and the constraints + + + + diff --git a/src/Mod/Part/App/GeomPlate/BuildPlateSurfacePyImp.cpp b/src/Mod/Part/App/GeomPlate/BuildPlateSurfacePyImp.cpp new file mode 100644 index 0000000000..7cfdb8d904 --- /dev/null +++ b/src/Mod/Part/App/GeomPlate/BuildPlateSurfacePyImp.cpp @@ -0,0 +1,505 @@ +/*************************************************************************** + * Copyright (c) 2020 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 "GeomPlate/BuildPlateSurfacePy.h" +#include "GeomPlate/BuildPlateSurfacePy.cpp" +#include "GeomPlate/CurveConstraintPy.h" +#include "GeomPlate/PointConstraintPy.h" +#include "GeometryCurvePy.h" +#include "GeometrySurfacePy.h" +#include "Geometry2d.h" + +using namespace Part; + +/*! + * \brief BuildPlateSurfacePy::PyMake + * \code +v1=App.Vector(0,0,0) +v2=App.Vector(10,0,0) +v3=App.Vector(10,10,3) +v4=App.Vector(0,10,0) +v5=App.Vector(5,5,5) + +l1=Part.LineSegment(v1, v2) +l2=Part.LineSegment(v2, v3) +l3=Part.LineSegment(v3, v4) +l4=Part.LineSegment(v4, v1) + +c1=Part.GeomPlate.CurveConstraint(l1) +c2=Part.GeomPlate.CurveConstraint(l2) +c3=Part.GeomPlate.CurveConstraint(l3) +c4=Part.GeomPlate.CurveConstraint(l4) +c5=Part.GeomPlate.PointConstraint(v5) + +bp=Part.GeomPlate.BuildPlateSurface() +bp.add(c1) +bp.add(c2) +bp.add(c3) +bp.add(c4) +bp.add(c5) +bp.perform() +s=bp.surface() +bs=s.makeApprox() +Part.show(bs.toShape()) +Part.show(l1.toShape()) +Part.show(l2.toShape()) +Part.show(l3.toShape()) +Part.show(l4.toShape()) + +bp.surfInit() + * \endcode + */ +PyObject *BuildPlateSurfacePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of BuildPlateSurfacePy + return new BuildPlateSurfacePy(nullptr); +} + +// constructor method +int BuildPlateSurfacePy::PyInit(PyObject* args, PyObject* kwds) +{ + PyObject *surf = nullptr; + int degree = 3; + int nbPtsOnCur = 10; + int nbIter = 3; + double tol2d = 0.00001; + double tol3d = 0.0001; + double tolAng = 0.01; + double tolCurv = 0.1; + PyObject* anisotropy = Py_False; + + static char* keywords[] = {"Surface", "Degree", "NbPtsOnCur", "NbIter", "Tol2d", + "Tol3d", "TolAng", "TolCurv", "Anisotropy", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!iiiddddO!", keywords, + &(GeometrySurfacePy::Type), &surf, °ree, + &nbPtsOnCur, &nbIter, &tol2d, &tol3d, + &tolAng, &tolCurv, &PyBool_Type, &anisotropy)) + return -1; + + try { + std::unique_ptr ptr(new GeomPlate_BuildPlateSurface + (degree, nbPtsOnCur, nbIter, tol2d, tol3d, tolAng, tolCurv, + PyObject_IsTrue(anisotropy) ? Standard_True : Standard_False)); + + if (surf) { + GeomSurface* surface = static_cast(surf)->getGeomSurfacePtr(); + Handle(Geom_Surface) handle = Handle(Geom_Surface)::DownCast(surface->handle()); + if (handle.IsNull()) { + PyErr_SetString(PyExc_ReferenceError, "No valid surface handle"); + return -1; + } + ptr->LoadInitSurface(handle); + } + + setPointer(ptr.release()); + + return 0; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return -1; + } +} + +// returns a string which represents the object e.g. when printed in python +std::string BuildPlateSurfacePy::representation() const +{ + return std::string(""); +} + +PyObject* BuildPlateSurfacePy::init(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + getGeomPlate_BuildPlateSurfacePtr()->Init(); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::loadInitSurface(PyObject *args) +{ + PyObject* surf; + if (!PyArg_ParseTuple(args, "O!", &(GeometrySurfacePy::Type), &surf)) + return nullptr; + + GeomSurface* surface = static_cast(surf)->getGeomSurfacePtr(); + Handle(Geom_Surface) handle = Handle(Geom_Surface)::DownCast(surface->handle()); + if (handle.IsNull()) { + PyErr_SetString(PyExc_ReferenceError, "No valid surface handle"); + return nullptr; + } + + try { + getGeomPlate_BuildPlateSurfacePtr()->LoadInitSurface(handle); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::add(PyObject *args) +{ + PyObject* cont; + if (!PyArg_ParseTuple(args, "O", &cont)) + return nullptr; + + try { + if (PyObject_TypeCheck(cont, &PointConstraintPy::Type)) { + GeomPlate_PointConstraint* pc = static_cast(cont)->getGeomPlate_PointConstraintPtr(); + getGeomPlate_BuildPlateSurfacePtr()->Add(new GeomPlate_PointConstraint(*pc)); + Py_Return; + } + else if (PyObject_TypeCheck(cont, &CurveConstraintPy::Type)) { + GeomPlate_CurveConstraint* cc = static_cast(cont)->getGeomPlate_CurveConstraintPtr(); + getGeomPlate_BuildPlateSurfacePtr()->Add(new GeomPlate_CurveConstraint(*cc)); + Py_Return; + } + else { + PyErr_SetString(PyExc_TypeError, "PointConstraint or CurveConstraint expected"); + return nullptr; + } + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::setNbBounds(PyObject *args) +{ + int count; + if (!PyArg_ParseTuple(args, "i", &count)) + return nullptr; + + try { + getGeomPlate_BuildPlateSurfacePtr()->SetNbBounds(count); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::perform(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + getGeomPlate_BuildPlateSurfacePtr()->Perform(); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::isDone(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Standard_Boolean ok = getGeomPlate_BuildPlateSurfacePtr()->IsDone(); + return Py_BuildValue("O", (ok ? Py_True : Py_False)); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::surface(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(Geom_Surface) hSurf = getGeomPlate_BuildPlateSurfacePtr()->Surface(); + if (hSurf.IsNull()) + Py_Return; + + std::unique_ptr geo(makeFromSurface(hSurf)); + return geo->getPyObject(); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::surfInit(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(Geom_Surface) hSurf = getGeomPlate_BuildPlateSurfacePtr()->SurfInit(); + if (hSurf.IsNull()) + Py_Return; + + std::unique_ptr geo(makeFromSurface(hSurf)); + return geo->getPyObject(); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::curveConstraint(PyObject *args) +{ + int index; + if (!PyArg_ParseTuple(args, "i", &index)) + return nullptr; + + try { + Handle(GeomPlate_CurveConstraint) hCC = getGeomPlate_BuildPlateSurfacePtr()->CurveConstraint(index); + if (hCC.IsNull()) + Py_Return; + + std::unique_ptr ptr(new GeomPlate_CurveConstraint(*hCC)); + return new CurveConstraintPy(ptr.release()); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::pointConstraint(PyObject *args) +{ + int index; + if (!PyArg_ParseTuple(args, "i", &index)) + return nullptr; + + try { + Handle(GeomPlate_PointConstraint) hPC = getGeomPlate_BuildPlateSurfacePtr()->PointConstraint(index); + if (hPC.IsNull()) + Py_Return; + + std::unique_ptr ptr(new GeomPlate_PointConstraint(*hPC)); + return new PointConstraintPy(ptr.release()); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::disc2dContour(PyObject *args) +{ + int index; + if (!PyArg_ParseTuple(args, "i", &index)) + return nullptr; + + try { + TColgp_SequenceOfXY seq2d; + getGeomPlate_BuildPlateSurfacePtr()->Disc2dContour(index, seq2d); + + Py::List list; + for (int i = seq2d.Lower(); i <= seq2d.Upper(); ++i) { + const gp_XY& pnt = seq2d.Value(i); + Py::Tuple coord(2); + coord.setItem(0, Py::Float(pnt.X())); + coord.setItem(1, Py::Float(pnt.Y())); + list.append(coord); + } + + return Py::new_reference_to(list); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::disc3dContour(PyObject *args) +{ + int index, order; + if (!PyArg_ParseTuple(args, "ii", &index, &order)) + return nullptr; + + try { + TColgp_SequenceOfXYZ seq3d; + getGeomPlate_BuildPlateSurfacePtr()->Disc3dContour(index, order, seq3d); + + Py::List list; + for (int i = seq3d.Lower(); i <= seq3d.Upper(); ++i) { + const gp_XYZ& pnt = seq3d.Value(i); + Py::Tuple coord(3); + coord.setItem(0, Py::Float(pnt.X())); + coord.setItem(1, Py::Float(pnt.Y())); + coord.setItem(2, Py::Float(pnt.Z())); + list.append(coord); + } + + return Py::new_reference_to(list); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::sense(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(TColStd_HArray1OfInteger) hOrder = getGeomPlate_BuildPlateSurfacePtr()->Sense(); + Py::List list; + if (!hOrder.IsNull()) { + for (auto i = hOrder->Lower(); i <= hOrder->Upper(); ++i) { + list.append(Py::Long(hOrder->Value(i))); + } + } + return Py::new_reference_to(list); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::curves2d(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(TColGeom2d_HArray1OfCurve) hCurves = getGeomPlate_BuildPlateSurfacePtr()->Curves2d(); + Py::List list; + if (!hCurves.IsNull()) { + for (auto i = hCurves->Lower(); i <= hCurves->Upper(); ++i) { + Handle(Geom2d_Curve) hCurve = hCurves->Value(i); + std::unique_ptr ptr(makeFromCurve2d(hCurve)); + if (ptr) + list.append(Py::asObject(ptr->getPyObject())); + } + } + return Py::new_reference_to(list); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::order(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(TColStd_HArray1OfInteger) hOrder = getGeomPlate_BuildPlateSurfacePtr()->Order(); + Py::List list; + if (!hOrder.IsNull()) { + for (auto i = hOrder->Lower(); i <= hOrder->Upper(); ++i) { + list.append(Py::Long(hOrder->Value(i))); + } + } + return Py::new_reference_to(list); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::G0Error(PyObject *args) +{ + int index = 0; + if (!PyArg_ParseTuple(args, "|i", &index)) + return nullptr; + + try { + Standard_Real v = index < 1 ? getGeomPlate_BuildPlateSurfacePtr()->G0Error() + : getGeomPlate_BuildPlateSurfacePtr()->G0Error(index); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::G1Error(PyObject *args) +{ + int index = 0; + if (!PyArg_ParseTuple(args, "|i", &index)) + return nullptr; + + try { + Standard_Real v = index < 1 ? getGeomPlate_BuildPlateSurfacePtr()->G1Error() + : getGeomPlate_BuildPlateSurfacePtr()->G1Error(index); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* BuildPlateSurfacePy::G2Error(PyObject *args) +{ + int index = 0; + if (!PyArg_ParseTuple(args, "|i", &index)) + return nullptr; + + try { + Standard_Real v = index < 1 ? getGeomPlate_BuildPlateSurfacePtr()->G2Error() + : getGeomPlate_BuildPlateSurfacePtr()->G2Error(index); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject *BuildPlateSurfacePy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int BuildPlateSurfacePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Part/App/GeomPlate/CurveConstraintPy.xml b/src/Mod/Part/App/GeomPlate/CurveConstraintPy.xml new file mode 100644 index 0000000000..4e0e12b7d3 --- /dev/null +++ b/src/Mod/Part/App/GeomPlate/CurveConstraintPy.xml @@ -0,0 +1,136 @@ + + + + + + Defines curves as constraints to be used to deform a surface + + + + Allows you to set the order of continuity required for +the constraints: G0, G1, and G2, controlled +respectively by G0Criterion G1Criterion and G2Criterion. + + + + + + Returns the order of constraint, one of G0, G1 or G2 + + + + + Returns the G0 criterion at the parametric point U on +the curve. This is the greatest distance allowed between +the constraint and the target surface at U. + + + + + + Returns the G1 criterion at the parametric point U on +the curve. This is the greatest angle allowed between +the constraint and the target surface at U. +Raises an exception if the curve is not on a surface. + + + + + + Returns the G2 criterion at the parametric point U on +the curve. This is the greatest difference in curvature +allowed between the constraint and the target surface at U. +Raises an exception if the curve is not on a surface. + + + + + + Allows you to set the G0 criterion. This is the law +defining the greatest distance allowed between the +constraint and the target surface for each point of the +constraint. If this criterion is not set, TolDist, the +distance tolerance from the constructor, is used. + + + + + + Allows you to set the G1 criterion. This is the law +defining the greatest angle allowed between the +constraint and the target surface. If this criterion is not +set, TolAng, the angular tolerance from the constructor, is used. +Raises an exception if the curve is not on a surface + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The number of points on the curve used as a +constraint. The default setting is 10. This parameter +affects computation time, which increases by the cube of +the number of points. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp b/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp new file mode 100644 index 0000000000..62af3356d2 --- /dev/null +++ b/src/Mod/Part/App/GeomPlate/CurveConstraintPyImp.cpp @@ -0,0 +1,387 @@ +/*************************************************************************** + * Copyright (c) 2020 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 +# include +# include +# include +# include +#endif + +#include "GeomPlate/CurveConstraintPy.h" +#include "GeomPlate/CurveConstraintPy.cpp" +#include "Geom2d/Curve2dPy.h" +#include "GeometryCurvePy.h" +#include "GeometrySurfacePy.h" +#include "Geometry2d.h" + +using namespace Part; + +PyObject *CurveConstraintPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of CurveConstraintPy and the Twin object + return new CurveConstraintPy(nullptr); +} + +// constructor method +int CurveConstraintPy::PyInit(PyObject* args, PyObject* kwds) +{ + PyObject *bound = nullptr; + int order = 0; + int nbPts = 10; + double tolDist = 0.0001; + double tolAng = 0.01; + double tolCurv = 0.1; + + // GeomPlate_CurveConstraint has a default constructor but OCCT doesn't check + // if neither a 2d, 3d or curve on surface is set when accessing the functions + // Length(), FirstParameter(), LastParameter(), ... + // Thus, we don't allow to create an empty GeomPlate_CurveConstraint instance + + static char* keywords[] = {"Boundary", "Order", "NbPts", "TolDist", "TolAng", "TolCurv", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|iiddd", keywords, + &(GeometryCurvePy::Type), &bound, &order, + &nbPts, &tolDist, &tolAng, &tolCurv)) + return -1; + + try { + std::unique_ptr ptr; + if (bound) { + GeomCurve* curve = static_cast(bound)->getGeomCurvePtr(); + Handle(Geom_Curve) handle = Handle(Geom_Curve)::DownCast(curve->handle()); + if (handle.IsNull()) { + PyErr_SetString(PyExc_ReferenceError, "No valid curve handle"); + return -1; + } + + Handle(Adaptor3d_HCurve) hCurve; + if (curve->getTypeId().isDerivedFrom(GeomTrimmedCurve::getClassTypeId())) { + GeomTrimmedCurve* trim = static_cast(curve); + GeomAdaptor_Curve adapt(handle, trim->getFirstParameter(), trim->getLastParameter()); + hCurve = new GeomAdaptor_HCurve(adapt); + } + else { + GeomAdaptor_Curve adapt(handle); + hCurve = new GeomAdaptor_HCurve(adapt); + } + + ptr.reset(new GeomPlate_CurveConstraint(hCurve, order, nbPts, tolDist, tolAng, tolCurv)); + } + else { + ptr.reset(new GeomPlate_CurveConstraint); + } + + setPointer(ptr.release()); + + return 0; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return -1; + } +} + +// returns a string which represents the object e.g. when printed in python +std::string CurveConstraintPy::representation(void) const +{ + return std::string(""); +} + +PyObject* CurveConstraintPy::setOrder(PyObject *args) +{ + int order; + if (!PyArg_ParseTuple(args, "i", &order)) + return nullptr; + + try { + getGeomPlate_CurveConstraintPtr()->SetOrder(order); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::order(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Standard_Integer v = getGeomPlate_CurveConstraintPtr()->Order(); + return PyLong_FromLong(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::G0Criterion(PyObject *args) +{ + double u; + if (!PyArg_ParseTuple(args, "d", &u)) + return nullptr; + + try { + Standard_Real v = getGeomPlate_CurveConstraintPtr()->G0Criterion(u); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::G1Criterion(PyObject *args) +{ + double u; + if (!PyArg_ParseTuple(args, "d", &u)) + return nullptr; + + try { + Standard_Real v = getGeomPlate_CurveConstraintPtr()->G1Criterion(u); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::G2Criterion(PyObject *args) +{ + double u; + if (!PyArg_ParseTuple(args, "d", &u)) + return nullptr; + + try { + Standard_Real v = getGeomPlate_CurveConstraintPtr()->G2Criterion(u); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::setG0Criterion(PyObject *) +{ + PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); + return nullptr; +} + +PyObject* CurveConstraintPy::setG1Criterion(PyObject *) +{ + PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); + return nullptr; +} + +PyObject* CurveConstraintPy::setG2Criterion(PyObject *) +{ + PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); + return nullptr; +} + +PyObject* CurveConstraintPy::curve3d(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(Adaptor3d_HCurve) hAdapt = getGeomPlate_CurveConstraintPtr()->Curve3d(); + if (hAdapt.IsNull()) + Py_Return; + + const Adaptor3d_Curve& a3d = hAdapt->Curve(); + std::unique_ptr ptr(Part::makeFromCurveAdaptor(a3d)); + return ptr->getPyObject(); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::setCurve2dOnSurf(PyObject *args) +{ + PyObject* c; + if (!PyArg_ParseTuple(args, "O!", &Part::Curve2dPy::Type, &c)) + return nullptr; + + try { + Handle(Geom2d_Curve) curve2 = Handle(Geom2d_Curve)::DownCast(static_cast(c)->getGeometry2dPtr()->handle()); + if (curve2.IsNull()) { + PyErr_SetString(PyExc_ReferenceError, "No valid curve handle"); + return nullptr; + } + + getGeomPlate_CurveConstraintPtr()->SetCurve2dOnSurf(curve2); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::curve2dOnSurf(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(Geom2d_Curve) curve2 = getGeomPlate_CurveConstraintPtr()->Curve2dOnSurf(); + if (curve2.IsNull()) + Py_Return; + + std::unique_ptr ptr(Part::makeFromCurve2d(curve2)); + return ptr->getPyObject(); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::setProjectedCurve(PyObject *args) +{ + PyObject* c; + double tolU, tolV; + if (!PyArg_ParseTuple(args, "O!dd", &Part::Curve2dPy::Type, &c, &tolU, &tolV)) + return nullptr; + + try { + Geom2dCurve* curve2 = static_cast(c)->getGeom2dCurvePtr(); + Handle(Geom2d_Curve) handle = Handle(Geom2d_Curve)::DownCast(curve2->handle()); + if (handle.IsNull()) { + PyErr_SetString(PyExc_ReferenceError, "No valid curve handle"); + return nullptr; + } + + Handle(Adaptor2d_HCurve2d) hCurve; + if (handle->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { + Handle(Geom2d_TrimmedCurve) aTC (Handle(Geom2d_TrimmedCurve)::DownCast (handle)); + Geom2dAdaptor_Curve adapt(handle, aTC->FirstParameter(), aTC->LastParameter()); + hCurve = new Geom2dAdaptor_HCurve(adapt); + } + else { + Geom2dAdaptor_Curve adapt(handle); + hCurve = new Geom2dAdaptor_HCurve(adapt); + } + + getGeomPlate_CurveConstraintPtr()->SetProjectedCurve(hCurve, tolU, tolV); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* CurveConstraintPy::projectedCurve(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Handle(Adaptor2d_HCurve2d) hAdapt = getGeomPlate_CurveConstraintPtr()->ProjectedCurve(); + if (hAdapt.IsNull()) + Py_Return; + + const Adaptor2d_Curve2d& a2d = hAdapt->Curve2d(); + std::unique_ptr ptr(Part::makeFromCurveAdaptor2d(a2d)); + return ptr->getPyObject(); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +Py::Long CurveConstraintPy::getNbPoints(void) const +{ + try { + Standard_Integer v = getGeomPlate_CurveConstraintPtr()->NbPoints(); + return Py::Long(v); + } + catch (const Standard_Failure& e) { + throw Py::RuntimeError(e.GetMessageString()); + } +} + +void CurveConstraintPy::setNbPoints(Py::Long arg) +{ + try { + getGeomPlate_CurveConstraintPtr()->SetNbPoints(static_cast(arg)); + } + catch (const Standard_Failure& e) { + throw Py::RuntimeError(e.GetMessageString()); + } +} + +Py::Float CurveConstraintPy::getFirstParameter(void) const +{ + try { + Standard_Real v = getGeomPlate_CurveConstraintPtr()->FirstParameter(); + return Py::Float(v); + } + catch (const Standard_Failure& e) { + throw Py::RuntimeError(e.GetMessageString()); + } +} + +Py::Float CurveConstraintPy::getLastParameter(void) const +{ + try { + Standard_Real v = getGeomPlate_CurveConstraintPtr()->LastParameter(); + return Py::Float(v); + } + catch (const Standard_Failure& e) { + throw Py::RuntimeError(e.GetMessageString()); + } +} + +Py::Float CurveConstraintPy::getLength(void) const +{ + try { + Standard_Real v = getGeomPlate_CurveConstraintPtr()->Length(); + return Py::Float(v); + } + catch (const Standard_Failure& e) { + throw Py::RuntimeError(e.GetMessageString()); + } +} + +PyObject *CurveConstraintPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int CurveConstraintPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Part/App/GeomPlate/PointConstraintPy.xml b/src/Mod/Part/App/GeomPlate/PointConstraintPy.xml new file mode 100644 index 0000000000..bc357852b4 --- /dev/null +++ b/src/Mod/Part/App/GeomPlate/PointConstraintPy.xml @@ -0,0 +1,99 @@ + + + + + + Defines points as constraints to be used to deform a surface + + + + Allows you to set the order of continuity required for +the constraints: G0, G1, and G2, controlled +respectively by G0Criterion G1Criterion and G2Criterion. + + + + + + Returns the order of constraint, one of G0, G1 or G2 + + + + + Returns the G0 criterion at the parametric point U on +the curve. This is the greatest distance allowed between +the constraint and the target surface at U. + + + + + + Returns the G1 criterion at the parametric point U on +the curve. This is the greatest angle allowed between +the constraint and the target surface at U. +Raises an exception if the curve is not on a surface. + + + + + + Returns the G2 criterion at the parametric point U on +the curve. This is the greatest difference in curvature +allowed between the constraint and the target surface at U. +Raises an exception if the curve is not on a surface. + + + + + + Allows you to set the G0 criterion. This is the law +defining the greatest distance allowed between the +constraint and the target surface for each point of the +constraint. If this criterion is not set, TolDist, the +distance tolerance from the constructor, is used. + + + + + + Allows you to set the G1 criterion. This is the law +defining the greatest angle allowed between the +constraint and the target surface. If this criterion is not +set, TolAng, the angular tolerance from the constructor, is used. +Raises an exception if the curve is not on a surface + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Part/App/GeomPlate/PointConstraintPyImp.cpp b/src/Mod/Part/App/GeomPlate/PointConstraintPyImp.cpp new file mode 100644 index 0000000000..67ffc2e948 --- /dev/null +++ b/src/Mod/Part/App/GeomPlate/PointConstraintPyImp.cpp @@ -0,0 +1,258 @@ +/*************************************************************************** + * Copyright (c) 2020 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 "GeomPlate/PointConstraintPy.h" +#include "GeomPlate/PointConstraintPy.cpp" +#include "GeometryCurvePy.h" +#include "GeometrySurfacePy.h" +#include "Geometry2d.h" +#include + +using namespace Part; + +PyObject *PointConstraintPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of PointConstraintPy + return new PointConstraintPy(nullptr); +} + +// constructor method +int PointConstraintPy::PyInit(PyObject* args, PyObject* kwds) +{ + PyObject *pt; + int order = 0; + double tolDist = 0.0001; + + static char* keywords[] = {"Point", "Order", "TolDist", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|id", keywords, + &(Base::VectorPy::Type), &pt, &order, &tolDist)) + return -1; + + try { + std::unique_ptr ptr; + Base::Vector3d v = static_cast(pt)->value(); + + ptr.reset(new GeomPlate_PointConstraint(gp_Pnt(v.x, v.y, v.z), order, tolDist)); + setPointer(ptr.release()); + + return 0; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return -1; + } +} + +// returns a string which represents the object e.g. when printed in python +std::string PointConstraintPy::representation(void) const +{ + return std::string(""); +} + +PyObject* PointConstraintPy::setOrder(PyObject *args) +{ + int order; + if (!PyArg_ParseTuple(args, "i", &order)) + return nullptr; + + try { + getGeomPlate_PointConstraintPtr()->SetOrder(order); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::order(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Standard_Integer v = getGeomPlate_PointConstraintPtr()->Order(); + return PyLong_FromLong(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::G0Criterion(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Standard_Real v = getGeomPlate_PointConstraintPtr()->G0Criterion(); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::G1Criterion(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Standard_Real v = getGeomPlate_PointConstraintPtr()->G1Criterion(); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::G2Criterion(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Standard_Real v = getGeomPlate_PointConstraintPtr()->G2Criterion(); + return PyFloat_FromDouble(v); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::setG0Criterion(PyObject *args) +{ + double tolDist; + if (!PyArg_ParseTuple(args, "d", &tolDist)) + return nullptr; + + try { + getGeomPlate_PointConstraintPtr()->SetG0Criterion(tolDist); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::setG1Criterion(PyObject *args) +{ + double tolAng; + if (!PyArg_ParseTuple(args, "d", &tolAng)) + return nullptr; + + try { + getGeomPlate_PointConstraintPtr()->SetG1Criterion(tolAng); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::setG2Criterion(PyObject *args) +{ + double tolCurv; + if (!PyArg_ParseTuple(args, "d", &tolCurv)) + return nullptr; + + try { + getGeomPlate_PointConstraintPtr()->SetG2Criterion(tolCurv); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::hasPnt2dOnSurf(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + Standard_Boolean ok = getGeomPlate_PointConstraintPtr()->HasPnt2dOnSurf(); + return Py_BuildValue("O", (ok ? Py_True : Py_False)); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::setPnt2dOnSurf(PyObject *args) +{ + double x, y; + if (!PyArg_ParseTuple(args, "dd", &x, &y)) + return nullptr; + + try { + getGeomPlate_PointConstraintPtr()->SetPnt2dOnSurf(gp_Pnt2d(x, y)); + Py_Return; + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* PointConstraintPy::pnt2dOnSurf(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + try { + gp_Pnt2d pt = getGeomPlate_PointConstraintPtr()->Pnt2dOnSurf(); + Py::Tuple coord(2); + coord.setItem(0, Py::Float(pt.X())); + coord.setItem(1, Py::Float(pt.Y())); + return Py::new_reference_to(coord); + } + catch (const Standard_Failure& e) { + PyErr_SetString(PyExc_RuntimeError, e.GetMessageString()); + return nullptr; + } +} + +PyObject *PointConstraintPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int PointConstraintPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index ab70d051d9..f22b8d79f2 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -5108,6 +5108,16 @@ std::unique_ptr makeFromCurveAdaptor(const Adaptor3d_Curve& adapt) if (!geoCurve) throw Base::TypeError("Unhandled curve type"); + + // Check if the curve must be trimmed + Handle(Geom_Curve) curv3d = Handle(Geom_Curve)::DownCast + (geoCurve->handle()); + double u = curv3d->FirstParameter(); + double v = curv3d->LastParameter(); + if (u != adapt.FirstParameter() || v != adapt.LastParameter()) { + geoCurve = makeFromTrimmedCurve(curv3d, adapt.FirstParameter(), adapt.LastParameter()); + } + return geoCurve; } diff --git a/src/Mod/Part/App/Geometry2d.cpp b/src/Mod/Part/App/Geometry2d.cpp index 1e60602f14..cdd822b8b8 100644 --- a/src/Mod/Part/App/Geometry2d.cpp +++ b/src/Mod/Part/App/Geometry2d.cpp @@ -2439,6 +2439,16 @@ std::unique_ptr makeFromCurveAdaptor2d(const Adaptor2d_Curve2d& ada if (!geoCurve) throw Base::TypeError("Unhandled curve type"); + + // Check if the curve must be trimmed + Handle(Geom2d_Curve) curv2d = Handle(Geom2d_Curve)::DownCast + (geoCurve->handle()); + double u = curv2d->FirstParameter(); + double v = curv2d->LastParameter(); + if (u != adapt.FirstParameter() || v != adapt.LastParameter()) { + geoCurve = makeFromTrimmedCurve2d(curv2d, adapt.FirstParameter(), adapt.LastParameter()); + } + return geoCurve; } }