From b10f83868714f43cb41d516992cc6eb8ac348612 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 20 Jan 2016 22:05:53 +0100 Subject: [PATCH] + simplify porting of Part module to Python3 --- src/Mod/Part/App/AppPart.cpp | 15 +- src/Mod/Part/App/AppPartPy.cpp | 2995 +++++++++++++++---------------- src/Mod/Part/Gui/AppPartGui.cpp | 31 +- 3 files changed, 1477 insertions(+), 1564 deletions(-) diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 736c2bba6..90ec5ef9a 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -91,19 +91,20 @@ #include "PartFeaturePy.h" #include "PropertyGeometryList.h" -extern struct PyMethodDef Part_methods[]; +namespace Part { +extern PyObject* initModule(); +} + using namespace Part; + PyObject* Part::PartExceptionOCCError; PyObject* Part::PartExceptionOCCDomainError; PyObject* Part::PartExceptionOCCRangeError; PyObject* Part::PartExceptionOCCConstructionError; PyObject* Part::PartExceptionOCCDimensionError; -PyDoc_STRVAR(module_part_doc, -"This is a module working with shapes."); -extern "C" { -void PartExport initPart() +PyMODINIT_FUNC initPart() { std::stringstream str; str << OCC_VERSION_MAJOR << "." << OCC_VERSION_MINOR << "." << OCC_VERSION_MAINTENANCE; @@ -122,7 +123,7 @@ void PartExport initPart() OSD::SetSignal(Standard_False); #endif - PyObject* partModule = Py_InitModule3("Part", Part_methods, module_part_doc); /* mod name, table ptr */ + PyObject* partModule = Part::initModule(); Base::Console().Log("Loading Part module... done\n"); PyObject* OCCError = 0; if (PyObject_IsSubclass(Base::BaseExceptionFreeCADError, @@ -381,5 +382,3 @@ void PartExport initPart() Interface_Static::SetCVal("write.step.product.name", hStepGrp->GetASCII("Product", Interface_Static::CVal("write.step.product.name")).c_str()); } - -} // extern "C" diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 7d6b5e95c..7707d75aa 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -79,6 +79,9 @@ # include #endif +#include +#include + #include #include #include @@ -126,1361 +129,16 @@ # include "FT2FC.h" #endif -using Base::Console; -using namespace Part; -using namespace std; - extern const char* BRepBuilderAPI_FaceErrorText(BRepBuilderAPI_FaceError fe); #ifndef M_PI - #define M_PI 3.14159265358979323846 /* pi */ +#define M_PI 3.14159265358979323846 /* pi */ #endif #ifndef M_PI_2 - #define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ #endif -/* module functions */ -static PyObject * open(PyObject *self, PyObject *args) -{ - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - - PY_TRY { - //Base::Console().Log("Open in Part with %s",Name); - Base::FileInfo file(EncodedName.c_str()); - - // extract ending - if (file.extension() == "") - Py_Error(Base::BaseExceptionFreeCADError,"no file ending"); - - if (file.hasExtension("stp") || file.hasExtension("step")) { - // create new document and add Import feature - App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); -#if 1 - ImportStepParts(pcDoc,EncodedName.c_str()); -#else - Part::ImportStep *pcFeature = (Part::ImportStep *)pcDoc->addObject("Part::ImportStep",file.fileNamePure().c_str()); - pcFeature->FileName.setValue(Name); -#endif - pcDoc->recompute(); - } -#if 1 - else if (file.hasExtension("igs") || file.hasExtension("iges")) { - App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); - ImportIgesParts(pcDoc,EncodedName.c_str()); - pcDoc->recompute(); - } -#endif - else { - try { - TopoShape shape; - shape.read(EncodedName.c_str()); - - // create new document set loaded shape - App::Document *pcDoc = App::GetApplication().newDocument(file.fileNamePure().c_str()); - Part::Feature *object = static_cast(pcDoc->addObject - ("Part::Feature",file.fileNamePure().c_str())); - object->Shape.setValue(shape); - pcDoc->recompute(); - } - catch (const Base::Exception& e) { - Py_Error(Base::BaseExceptionFreeCADError, e.what()); - } - } - } PY_CATCH_OCC; - - Py_Return; -} - -/* module functions */ -static PyObject * insert(PyObject *self, PyObject *args) -{ - char* Name; - const char* DocName; - if (!PyArg_ParseTuple(args, "ets","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - - PY_TRY { - //Base::Console().Log("Insert in Part with %s",Name); - Base::FileInfo file(EncodedName.c_str()); - - // extract ending - if (file.extension() == "") - Py_Error(Base::BaseExceptionFreeCADError,"no file ending"); - App::Document *pcDoc = App::GetApplication().getDocument(DocName); - if (!pcDoc) { - pcDoc = App::GetApplication().newDocument(DocName); - } - - if (file.hasExtension("stp") || file.hasExtension("step")) { -#if 1 - ImportStepParts(pcDoc,EncodedName.c_str()); -#else - // add Import feature - Part::ImportStep *pcFeature = (Part::ImportStep *)pcDoc->addObject("Part::ImportStep",file.fileNamePure().c_str()); - pcFeature->FileName.setValue(Name); -#endif - pcDoc->recompute(); - } -#if 1 - else if (file.hasExtension("igs") || file.hasExtension("iges")) { - ImportIgesParts(pcDoc,EncodedName.c_str()); - pcDoc->recompute(); - } -#endif - else { - try { - TopoShape shape; - shape.read(EncodedName.c_str()); - - Part::Feature *object = static_cast(pcDoc->addObject - ("Part::Feature",file.fileNamePure().c_str())); - object->Shape.setValue(shape); - pcDoc->recompute(); - } - catch (const Base::Exception& e) { - Py_Error(Base::BaseExceptionFreeCADError, e.what()); - } - } - } PY_CATCH_OCC; - - Py_Return; -} - -/* module functions */ -static PyObject * exporter(PyObject *self, PyObject *args) -{ - PyObject* object; - char* Name; - if (!PyArg_ParseTuple(args, "Oet",&object,"utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - - BRep_Builder builder; - TopoDS_Compound comp; - builder.MakeCompound(comp); - - PY_TRY { - Py::Sequence list(object); - for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - PyObject* item = (*it).ptr(); - if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr(); - if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { - Part::Feature* part = static_cast(obj); - const TopoDS_Shape& shape = part->Shape.getValue(); - if (!shape.IsNull()) - builder.Add(comp, shape); - } - else { - Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue()); - } - } - } - - TopoShape shape(comp); - shape.write(EncodedName.c_str()); - - } PY_CATCH_OCC; - - Py_Return; -} - -/* module functions */ -static PyObject * read(PyObject *self, PyObject *args) -{ - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - PY_TRY { - TopoShape* shape = new TopoShape(); - shape->read(EncodedName.c_str()); - return new TopoShapePy(shape); - } PY_CATCH_OCC; -} - -static PyObject * -show(PyObject *self, PyObject *args) -{ - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - App::Document *pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(); - TopoShapePy* pShape = static_cast(pcObj); - Part::Feature *pcFeature = (Part::Feature *)pcDoc->addObject("Part::Feature", "Shape"); - // copy the data - //TopoShape* shape = new MeshObject(*pShape->getTopoShapeObjectPtr()); - pcFeature->Shape.setValue(pShape->getTopoShapePtr()->_Shape); - pcDoc->recompute(); - } PY_CATCH_OCC; - - Py_Return; -} - - -#ifdef FCUseFreeType - -static PyObject * makeWireString(PyObject *self, PyObject *args) -{ - PyObject *intext; - const char* dir; - const char* fontfile; - const char* fontspec; - bool useFontSpec = false; - double height; - double track = 0; - - Py_UNICODE *unichars; - Py_ssize_t pysize; - - PyObject *CharList; - - if (PyArg_ParseTuple(args, "Ossd|d", &intext, // compatibility with old version - &dir, - &fontfile, - &height, - &track)) { - useFontSpec = false; } - else { - PyErr_Clear(); - if (PyArg_ParseTuple(args, "Osd|d", &intext, - &fontspec, - &height, - &track)) { - useFontSpec = true; } - else { - Base::Console().Message("** makeWireString bad args.\n"); - return NULL; } - } - - if (PyString_Check(intext)) { - PyObject *p = Base::PyAsUnicodeObject(PyString_AsString(intext)); - if (!p) { - Base::Console().Message("** makeWireString can't convert PyString.\n"); - return NULL; - } - pysize = PyUnicode_GetSize(p); - unichars = PyUnicode_AS_UNICODE(p); - } - else if (PyUnicode_Check(intext)) { - pysize = PyUnicode_GetSize(intext); - unichars = PyUnicode_AS_UNICODE(intext); - } - else { - Base::Console().Message("** makeWireString bad text parameter.\n"); - return NULL; - } - - try { - if (useFontSpec) { - CharList = FT2FC(unichars,pysize,fontspec,height,track); } - else { - CharList = FT2FC(unichars,pysize,dir,fontfile,height,track); } - } - catch (Standard_DomainError) { // Standard_DomainError is OCC error. - PyErr_SetString(PartExceptionOCCDomainError, "makeWireString failed - Standard_DomainError"); - return NULL; - } - catch (std::runtime_error& e) { // FT2 or FT2FC errors - PyErr_SetString(PartExceptionOCCError, e.what()); - return NULL; - } - - return (CharList); -} -#else - -static PyObject * makeWireString(PyObject *self, PyObject *args) -{ - PyErr_SetString(Base::BaseExceptionFreeCADError, "FreeCAD compiled without FreeType support! This method is disabled..."); - return NULL; -} - -#endif //#ifdef FCUseFreeType -static PyObject * -makeCompound(PyObject *self, PyObject *args) -{ - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O", &pcObj)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - BRep_Builder builder; - TopoDS_Compound Comp; - builder.MakeCompound(Comp); - - try { - Py::Sequence list(pcObj); - for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) { - const TopoDS_Shape& sh = static_cast((*it).ptr())-> - getTopoShapePtr()->_Shape; - if (!sh.IsNull()) - builder.Add(Comp, sh); - } - } - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } - - return new TopoShapeCompoundPy(new TopoShape(Comp)); - } PY_CATCH_OCC; -} - -static PyObject * makeFilledFace(PyObject *self, PyObject *args) -{ - // TODO: BRepFeat_SplitShape - PyObject *obj; - PyObject *surf=0; - if (!PyArg_ParseTuple(args, "O|O!", &obj, &TopoShapeFacePy::Type, &surf)) - return NULL; - - PY_TRY { - // See also BRepOffsetAPI_MakeFilling - BRepFill_Filling builder; - try { - if (surf) { - const TopoDS_Shape& face = static_cast(surf)-> - getTopoShapePtr()->_Shape; - if (!face.IsNull() && face.ShapeType() == TopAbs_FACE) { - builder.LoadInitSurface(TopoDS::Face(face)); - } - } - Py::Sequence list(obj); - int numConstraints = 0; - for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) { - const TopoDS_Shape& sh = static_cast((*it).ptr())-> - getTopoShapePtr()->_Shape; - if (!sh.IsNull()) { - if (sh.ShapeType() == TopAbs_EDGE) { - builder.Add(TopoDS::Edge(sh), GeomAbs_C0); - numConstraints++; - } - else if (sh.ShapeType() == TopAbs_FACE) { - builder.Add(TopoDS::Face(sh), GeomAbs_C0); - numConstraints++; - } - else if (sh.ShapeType() == TopAbs_VERTEX) { - const TopoDS_Vertex& v = TopoDS::Vertex(sh); - gp_Pnt pnt = BRep_Tool::Pnt(v); - builder.Add(pnt); - numConstraints++; - } - } - } - } - - if (numConstraints == 0) { - PyErr_SetString(PartExceptionOCCError, "Failed to created face with no constraints"); - return 0; - } - - builder.Build(); - if (builder.IsDone()) { - return new TopoShapeFacePy(new TopoShape(builder.Face())); - } - else { - PyErr_SetString(PartExceptionOCCError, "Failed to created face by filling edges"); - return 0; - } - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } - } PY_CATCH_OCC; -} - -static PyObject * makeShell(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) - return NULL; - - PY_TRY { - BRep_Builder builder; - TopoDS_Shape shape; - TopoDS_Shell shell; - //BRepOffsetAPI_Sewing mkShell; - builder.MakeShell(shell); - - try { - Py::Sequence list(obj); - for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapeFacePy::Type))) { - const TopoDS_Shape& sh = static_cast((*it).ptr())-> - getTopoShapePtr()->_Shape; - if (!sh.IsNull()) - builder.Add(shell, sh); - } - } - - shape = shell; - BRepCheck_Analyzer check(shell); - if (!check.IsValid()) { - ShapeUpgrade_ShellSewing sewShell; - shape = sewShell.ApplySewing(shell); - } - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } - - return new TopoShapeShellPy(new TopoShape(shape)); - } PY_CATCH_OCC; -} - -static PyObject * makeSolid(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &obj)) - return NULL; - - try { - BRepBuilderAPI_MakeSolid mkSolid; - const TopoDS_Shape& shape = static_cast(obj) - ->getTopoShapePtr()->_Shape; - TopExp_Explorer anExp (shape, TopAbs_SHELL); - int count=0; - for (; anExp.More(); anExp.Next()) { - ++count; - mkSolid.Add(TopoDS::Shell(anExp.Current())); - } - - if (count == 0) - Standard_Failure::Raise("No shells found in shape"); - - TopoDS_Solid solid = mkSolid.Solid(); - BRepLib::OrientClosedSolid(solid); - return new TopoShapeSolidPy(new TopoShape(solid)); - } - catch (Standard_Failure) { - PyErr_SetString(PartExceptionOCCError, "creation of solid failed"); - return NULL; - } -} - -static PyObject * makePlane(PyObject *self, PyObject *args) -{ - double length, width; - PyObject *pPnt=0, *pDirZ=0, *pDirX=0; - if (!PyArg_ParseTuple(args, "dd|O!O!O!", &length, &width, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDirZ, - &(Base::VectorPy::Type), &pDirX)) - return NULL; - - if (length < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "length of plane too small"); - return NULL; - } - if (width < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "width of plane too small"); - return NULL; - } - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDirZ) { - Base::Vector3d vec = static_cast(pDirZ)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - Handle_Geom_Plane aPlane; - if (pDirX) { - Base::Vector3d vec = static_cast(pDirX)->value(); - gp_Dir dx; - dx.SetCoord(vec.x, vec.y, vec.z); - aPlane = new Geom_Plane(gp_Ax3(p, d, dx)); - } - else { - aPlane = new Geom_Plane(p, d); - } - - BRepBuilderAPI_MakeFace Face(aPlane, 0.0, length, 0.0, width -#if OCC_VERSION_HEX >= 0x060502 - , Precision::Confusion() -#endif - ); - return new TopoShapeFacePy(new TopoShape((Face.Face()))); - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of plane failed"); - return NULL; - } - catch (Standard_Failure) { - PyErr_SetString(PartExceptionOCCError, "creation of plane failed"); - return NULL; - } -} - -static PyObject * makeBox(PyObject *self, PyObject *args) -{ - double length, width, height; - PyObject *pPnt=0, *pDir=0; - if (!PyArg_ParseTuple(args, "ddd|O!O!", &length, &width, &height, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir)) - return NULL; - - if (length < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "length of box too small"); - return NULL; - } - if (width < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "width of box too small"); - return NULL; - } - if (height < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "height of box too small"); - return NULL; - } - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - BRepPrimAPI_MakeBox mkBox(gp_Ax2(p,d), length, width, height); - TopoDS_Shape ResultShape = mkBox.Shape(); - return new TopoShapeSolidPy(new TopoShape(ResultShape)); - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of box failed"); - return NULL; - } -} - -static PyObject * makeWedge(PyObject *self, PyObject *args) -{ - double xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max; - PyObject *pPnt=0, *pDir=0; - if (!PyArg_ParseTuple(args, "dddddddddd|O!O!", - &xmin, &ymin, &zmin, &z2min, &x2min, &xmax, &ymax, &zmax, &z2max, &x2max, - &(Base::VectorPy::Type), &pPnt, &(Base::VectorPy::Type), &pDir)) - return NULL; - - double dx = xmax-xmin; - double dy = ymax-ymin; - double dz = zmax-zmin; - double dz2 = z2max-z2min; - double dx2 = x2max-x2min; - if (dx < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "delta x of wedge too small"); - return NULL; - } - if (dy < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "delta y of wedge too small"); - return NULL; - } - if (dz < Precision::Confusion()) { - PyErr_SetString(PartExceptionOCCError, "delta z of wedge too small"); - return NULL; - } - if (dz2 < 0) { - PyErr_SetString(PartExceptionOCCError, "delta z2 of wedge is negative"); - return NULL; - } - if (dx2 < 0) { - PyErr_SetString(PartExceptionOCCError, "delta x2 of wedge is negative"); - return NULL; - } - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - BRepPrim_Wedge mkWedge(gp_Ax2(p,d), xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max); - BRepBuilderAPI_MakeSolid mkSolid; - mkSolid.Add(mkWedge.Shell()); - return new TopoShapeSolidPy(new TopoShape(mkSolid.Solid())); - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of wedge failed"); - return NULL; - } -} - -static PyObject * makeCircle(PyObject *self, PyObject *args) -{ - double radius, angle1=0.0, angle2=360; - PyObject *pPnt=0, *pDir=0; - if (!PyArg_ParseTuple(args, "d|O!O!dd", &radius, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir, - &angle1, &angle2)) - return NULL; - - try { - gp_Pnt loc(0,0,0); - gp_Dir dir(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - loc.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - dir.SetCoord(vec.x, vec.y, vec.z); - } - gp_Ax1 axis(loc, dir); - gp_Circ circle; - circle.SetAxis(axis); - circle.SetRadius(radius); - - Handle_Geom_Circle hCircle = new Geom_Circle (circle); - BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, angle1*(M_PI/180), angle2*(M_PI/180)); - TopoDS_Edge edge = aMakeEdge.Edge(); - return new TopoShapeEdgePy(new TopoShape(edge)); - } - catch (Standard_Failure) { - PyErr_SetString(PartExceptionOCCError, "creation of circle failed"); - return NULL; - } -} - -static PyObject * makeSphere(PyObject *self, PyObject *args) -{ - double radius, angle1=-90, angle2=90, angle3=360; - PyObject *pPnt=0, *pDir=0; - if (!PyArg_ParseTuple(args, "d|O!O!ddd", &radius, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir, - &angle1, &angle2, &angle3)) - return NULL; - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - BRepPrimAPI_MakeSphere mkSphere(gp_Ax2(p,d), radius, angle1*(M_PI/180), angle2*(M_PI/180), angle3*(M_PI/180)); - TopoDS_Shape shape = mkSphere.Shape(); - return new TopoShapeSolidPy(new TopoShape(shape)); - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of sphere failed"); - return NULL; - } -} - -static PyObject * makeCylinder(PyObject *self, PyObject *args) -{ - double radius, height, angle=360; - PyObject *pPnt=0, *pDir=0; - if (!PyArg_ParseTuple(args, "dd|O!O!d", &radius, &height, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir, - &angle)) - return NULL; - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - BRepPrimAPI_MakeCylinder mkCyl(gp_Ax2(p,d),radius, height, angle*(M_PI/180)); - TopoDS_Shape shape = mkCyl.Shape(); - return new TopoShapeSolidPy(new TopoShape(shape)); - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of cylinder failed"); - return NULL; - } -} - -static PyObject * makeCone(PyObject *self, PyObject *args) -{ - double radius1, radius2, height, angle=360; - PyObject *pPnt=0, *pDir=0; - if (!PyArg_ParseTuple(args, "ddd|O!O!d", &radius1, &radius2, &height, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir, - &angle)) - return NULL; - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - BRepPrimAPI_MakeCone mkCone(gp_Ax2(p,d),radius1, radius2, height, angle*(M_PI/180)); - TopoDS_Shape shape = mkCone.Shape(); - return new TopoShapeSolidPy(new TopoShape(shape)); - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of cone failed"); - return NULL; - } -} - -static PyObject * makeTorus(PyObject *self, PyObject *args) -{ - double radius1, radius2, angle1=0.0, angle2=360, angle=360; - PyObject *pPnt=0, *pDir=0; - if (!PyArg_ParseTuple(args, "dd|O!O!ddd", &radius1, &radius2, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir, - &angle1, &angle2, &angle)) - return NULL; - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - BRepPrimAPI_MakeTorus mkTorus(gp_Ax2(p,d), radius1, radius2, angle1*(M_PI/180), angle2*(M_PI/180), angle*(M_PI/180)); - const TopoDS_Shape& shape = mkTorus.Shape(); - return new TopoShapeSolidPy(new TopoShape(shape)); - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of torus failed"); - return NULL; - } -} - -static PyObject * makeHelix(PyObject *self, PyObject *args) -{ - double pitch, height, radius, angle=-1.0; - PyObject *pleft=Py_False; - PyObject *pvertHeight=Py_False; - if (!PyArg_ParseTuple(args, "ddd|dO!O!", &pitch, &height, &radius, &angle, - &(PyBool_Type), &pleft, - &(PyBool_Type), &pvertHeight)) - return 0; - - try { - TopoShape helix; - Standard_Boolean anIsLeft = PyObject_IsTrue(pleft) ? Standard_True : Standard_False; - Standard_Boolean anIsVertHeight = PyObject_IsTrue(pvertHeight) ? Standard_True : Standard_False; - TopoDS_Shape wire = helix.makeHelix(pitch, height, radius, angle, - anIsLeft, anIsVertHeight); - return new TopoShapeWirePy(new TopoShape(wire)); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } -} - -static PyObject * makeLongHelix(PyObject *self, PyObject *args) -{ - double pitch, height, radius, angle=-1.0; - PyObject *pleft=Py_False; - if (!PyArg_ParseTuple(args, "ddd|dO!", &pitch, &height, &radius, &angle, - &(PyBool_Type), &pleft)) { - Base::Console().Message("Part.makeLongHelix fails on parms\n"); - return 0; - } - - try { - TopoShape helix; - Standard_Boolean anIsLeft = PyObject_IsTrue(pleft) ? Standard_True : Standard_False; - TopoDS_Shape wire = helix.makeLongHelix(pitch, height, radius, angle, anIsLeft); - return new TopoShapeWirePy(new TopoShape(wire)); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } -} - -static PyObject * makeThread(PyObject *self, PyObject *args) -{ - double pitch, depth, height, radius; - if (!PyArg_ParseTuple(args, "dddd", &pitch, &depth, &height, &radius)) - return 0; - - try { - TopoShape helix; - TopoDS_Shape wire = helix.makeThread(pitch, depth, height, radius); - return new TopoShapeWirePy(new TopoShape(wire)); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } -} - -static PyObject * makeLine(PyObject *self, PyObject *args) -{ - PyObject *obj1, *obj2; - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) - return NULL; - - Base::Vector3d pnt1, pnt2; - if (PyObject_TypeCheck(obj1, &(Base::VectorPy::Type))) { - pnt1 = static_cast(obj1)->value(); - } - else if (PyObject_TypeCheck(obj1, &PyTuple_Type)) { - try { - pnt1 = Base::getVectorFromTuple(obj1); - } - catch (const Py::Exception&) { - return NULL; - } - } - else { - PyErr_SetString(PyExc_TypeError, "first argument must either be vector or tuple"); - return 0; - } - if (PyObject_TypeCheck(obj2, &(Base::VectorPy::Type))) { - pnt2 = static_cast(obj2)->value(); - } - else if (PyObject_TypeCheck(obj2, &PyTuple_Type)) { - try { - pnt2 = Base::getVectorFromTuple(obj2); - } - catch (const Py::Exception&) { - return NULL; - } - } - else { - PyErr_SetString(PyExc_TypeError, "second argument must either be vector or tuple"); - return 0; - } - - // Create directly the underlying line geometry - BRepBuilderAPI_MakeEdge makeEdge(gp_Pnt(pnt1.x, pnt1.y, pnt1.z), - gp_Pnt(pnt2.x, pnt2.y, pnt2.z)); - - const char *error=0; - switch (makeEdge.Error()) - { - case BRepBuilderAPI_EdgeDone: - break; // ok - case BRepBuilderAPI_PointProjectionFailed: - error = "Point projection failed"; - break; - case BRepBuilderAPI_ParameterOutOfRange: - error = "Parameter out of range"; - break; - case BRepBuilderAPI_DifferentPointsOnClosedCurve: - error = "Different points on closed curve"; - break; - case BRepBuilderAPI_PointWithInfiniteParameter: - error = "Point with infinite parameter"; - break; - case BRepBuilderAPI_DifferentsPointAndParameter: - error = "Different point and parameter"; - break; - case BRepBuilderAPI_LineThroughIdenticPoints: - error = "Line through identic points"; - break; - } - // Error - if (error) { - PyErr_SetString(PartExceptionOCCError, error); - return NULL; - } - - TopoDS_Edge edge = makeEdge.Edge(); - return new TopoShapeEdgePy(new TopoShape(edge)); -} - -static PyObject * makePolygon(PyObject *self, PyObject *args) -{ - PyObject *pcObj; - PyObject *pclosed=Py_False; - if (!PyArg_ParseTuple(args, "O|O!", &pcObj, &(PyBool_Type), &pclosed)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - BRepBuilderAPI_MakePolygon mkPoly; - try { - Py::Sequence list(pcObj); - for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Base::VectorPy::Type))) { - Base::Vector3d v = static_cast((*it).ptr())->value(); - mkPoly.Add(gp_Pnt(v.x,v.y,v.z)); - } - else if (PyObject_TypeCheck((*it).ptr(), &PyTuple_Type)) { - try { - Base::Vector3d v = Base::getVectorFromTuple((*it).ptr()); - mkPoly.Add(gp_Pnt(v.x,v.y,v.z)); - } - catch (const Py::Exception&) { - return 0; - } - } - } - - if (!mkPoly.IsDone()) - Standard_Failure::Raise("Cannot create polygon because less than two vertices are given"); - - // if the polygon should be closed - if (PyObject_IsTrue(pclosed)) { - if (!mkPoly.FirstVertex().IsSame(mkPoly.LastVertex())) { - mkPoly.Add(mkPoly.FirstVertex()); - } - } - - return new TopoShapeWirePy(new TopoShape(mkPoly.Wire())); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } - } PY_CATCH_OCC; -} - -static PyObject * makeRevolution(PyObject *self, PyObject *args) -{ - double vmin = DBL_MAX, vmax=-DBL_MAX; - double angle=360; - PyObject *pPnt=0, *pDir=0, *pCrv; - Handle_Geom_Curve curve; - union PyType_Object defaultType = {&Part::TopoShapeSolidPy::Type}; - PyObject* type = defaultType.o; - if (PyArg_ParseTuple(args, "O!|dddO!O!O!", &(GeometryPy::Type), &pCrv, - &vmin, &vmax, &angle, - &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir, - &(PyType_Type), &type)) { - GeometryPy* pcGeo = static_cast(pCrv); - curve = Handle_Geom_Curve::DownCast - (pcGeo->getGeometryPtr()->handle()); - if (curve.IsNull()) { - PyErr_SetString(PyExc_TypeError, "geometry is not a curve"); - return 0; - } - if (vmin == DBL_MAX) - vmin = curve->FirstParameter(); - - if (vmax == -DBL_MAX) - vmax = curve->LastParameter(); - } - else { - PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O!|dddO!O!", &(TopoShapePy::Type), &pCrv, - &vmin, &vmax, &angle, &(Base::VectorPy::Type), &pPnt, - &(Base::VectorPy::Type), &pDir)) { - return 0; - } - const TopoDS_Shape& shape = static_cast(pCrv)->getTopoShapePtr()->_Shape; - if (shape.IsNull()) { - PyErr_SetString(PartExceptionOCCError, "shape is empty"); - return 0; - } - - if (shape.ShapeType() != TopAbs_EDGE) { - PyErr_SetString(PartExceptionOCCError, "shape is not an edge"); - return 0; - } - - const TopoDS_Edge& edge = TopoDS::Edge(shape); - BRepAdaptor_Curve adapt(edge); - - const Handle_Geom_Curve& hCurve = adapt.Curve().Curve(); - // Apply placement of the shape to the curve - TopLoc_Location loc = edge.Location(); - curve = Handle_Geom_Curve::DownCast(hCurve->Transformed(loc.Transformation())); - if (curve.IsNull()) { - PyErr_SetString(PartExceptionOCCError, "invalid curve in edge"); - return 0; - } - - if (vmin == DBL_MAX) - vmin = adapt.FirstParameter(); - if (vmax == -DBL_MAX) - vmax = adapt.LastParameter(); - } - - try { - gp_Pnt p(0,0,0); - gp_Dir d(0,0,1); - if (pPnt) { - Base::Vector3d pnt = static_cast(pPnt)->value(); - p.SetCoord(pnt.x, pnt.y, pnt.z); - } - if (pDir) { - Base::Vector3d vec = static_cast(pDir)->value(); - d.SetCoord(vec.x, vec.y, vec.z); - } - - union PyType_Object shellType = {&Part::TopoShapeShellPy::Type}; - union PyType_Object faceType = {&Part::TopoShapeFacePy::Type}; - - BRepPrimAPI_MakeRevolution mkRev(gp_Ax2(p,d),curve, vmin, vmax, angle*(M_PI/180)); - if (type == defaultType.o) { - TopoDS_Shape shape = mkRev.Solid(); - return new TopoShapeSolidPy(new TopoShape(shape)); - } - else if (type == shellType.o) { - TopoDS_Shape shape = mkRev.Shell(); - return new TopoShapeShellPy(new TopoShape(shape)); - } - else if (type == faceType.o) { - TopoDS_Shape shape = mkRev.Face(); - return new TopoShapeFacePy(new TopoShape(shape)); - } - else { - TopoDS_Shape shape = mkRev.Shape(); - return new TopoShapePy(new TopoShape(shape)); - } - } - catch (Standard_DomainError) { - PyErr_SetString(PartExceptionOCCDomainError, "creation of revolved shape failed"); - return NULL; - } -} - -static PyObject * makeRuledSurface(PyObject *self, PyObject *args) -{ - // http://opencascade.blogspot.com/2009/10/surface-modeling-part1.html - PyObject *sh1, *sh2; - if (!PyArg_ParseTuple(args, "O!O!", &(TopoShapePy::Type), &sh1, - &(TopoShapePy::Type), &sh2)) - return 0; - - const TopoDS_Shape& shape1 = static_cast(sh1)->getTopoShapePtr()->_Shape; - const TopoDS_Shape& shape2 = static_cast(sh2)->getTopoShapePtr()->_Shape; - - try { - if (shape1.ShapeType() == TopAbs_EDGE && shape2.ShapeType() == TopAbs_EDGE) { - TopoDS_Face face = BRepFill::Face(TopoDS::Edge(shape1), TopoDS::Edge(shape2)); - return new TopoShapeFacePy(new TopoShape(face)); - } - else if (shape1.ShapeType() == TopAbs_WIRE && shape2.ShapeType() == TopAbs_WIRE) { - TopoDS_Shell shell = BRepFill::Shell(TopoDS::Wire(shape1), TopoDS::Wire(shape2)); - return new TopoShapeShellPy(new TopoShape(shell)); - } - else { - PyErr_SetString(PartExceptionOCCError, "curves must either be edges or wires"); - return 0; - } - } - catch (Standard_Failure) { - PyErr_SetString(PartExceptionOCCError, "creation of ruled surface failed"); - return 0; - } -} - -static PyObject * makeSweepSurface(PyObject *self, PyObject *args) -{ - PyObject *path, *profile; - double tolerance=0.001; - int fillMode = 0; - - // Path + profile - if (!PyArg_ParseTuple(args, "O!O!|di", &(TopoShapePy::Type), &path, - &(TopoShapePy::Type), &profile, - &tolerance, &fillMode)) - return 0; - - try { - const TopoDS_Shape& path_shape = static_cast(path)->getTopoShapePtr()->_Shape; - const TopoDS_Shape& prof_shape = static_cast(profile)->getTopoShapePtr()->_Shape; - - TopoShape myShape(path_shape); - TopoDS_Shape face = myShape.makeSweep(prof_shape, tolerance, fillMode); - return new TopoShapeFacePy(new TopoShape(face)); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } -} - -static PyObject * makeTube(PyObject *self, PyObject *args) -{ - PyObject *pshape; - double radius; - double tolerance=0.001; - char* scont = "C0"; - int maxdegree = 3; - int maxsegment = 30; - - // Path + radius - if (!PyArg_ParseTuple(args, "O!d|sii", &(TopoShapePy::Type), &pshape, &radius, &scont, &maxdegree, &maxsegment)) - return 0; - std::string str_cont = scont; - int cont; - if (str_cont == "C0") - cont = (int)GeomAbs_C0; - else if (str_cont == "C1") - cont = (int)GeomAbs_C1; - else if (str_cont == "C2") - cont = (int)GeomAbs_C2; - else if (str_cont == "C3") - cont = (int)GeomAbs_C3; - else if (str_cont == "CN") - cont = (int)GeomAbs_CN; - else if (str_cont == "G1") - cont = (int)GeomAbs_G1; - else if (str_cont == "G2") - cont = (int)GeomAbs_G2; - else - cont = (int)GeomAbs_C0; - - try { - const TopoDS_Shape& path_shape = static_cast(pshape)->getTopoShapePtr()->_Shape; - TopoShape myShape(path_shape); - TopoDS_Shape face = myShape.makeTube(radius, tolerance, cont, maxdegree, maxsegment); - return new TopoShapeFacePy(new TopoShape(face)); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } -} - -static PyObject * makeLoft(PyObject *self, PyObject *args) -{ -#if 0 - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O", &pcObj)) // convert args: Python->C - return NULL; // NULL triggers exception - - NCollection_List theSections; - Py::Sequence list(pcObj); - for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Part::GeometryCurvePy::Type))) { - Handle_Geom_Curve hCurve = Handle_Geom_Curve::DownCast( - static_cast((*it).ptr())->getGeomCurvePtr()->handle()); - theSections.Append(hCurve); - } - } - - //populate section generator - GeomFill_SectionGenerator aSecGenerator; - for (NCollection_List::Iterator anIt(theSections); anIt.More(); anIt.Next()) { - const Handle_Geom_Curve& aCurve = anIt.Value(); - aSecGenerator.AddCurve (aCurve); - } - aSecGenerator.Perform (Precision::PConfusion()); - - Handle_GeomFill_Line aLine = new GeomFill_Line (theSections.Size()); - - //parameters - const Standard_Integer aMinDeg = 1, aMaxDeg = BSplCLib::MaxDegree(), aNbIt = 0; - Standard_Real aTol3d = 1e-4, aTol2d = Precision::Parametric (aTol3d); - - //algorithm - GeomFill_AppSurf anAlgo (aMinDeg, aMaxDeg, aTol3d, aTol2d, aNbIt); - anAlgo.Perform (aLine, aSecGenerator); - - if (!anAlgo.IsDone()) { - PyErr_SetString(PartExceptionOCCError, "Failed to create loft surface"); - return 0; - } - - Handle_Geom_BSplineSurface aRes; - aRes = new Geom_BSplineSurface(anAlgo.SurfPoles(), anAlgo.SurfWeights(), - anAlgo.SurfUKnots(), anAlgo.SurfVKnots(), anAlgo.SurfUMults(), anAlgo.SurfVMults(), - anAlgo.UDegree(), anAlgo.VDegree()); - return new BSplineSurfacePy(new GeomBSplineSurface(aRes)); -#else - PyObject *pcObj; - PyObject *psolid=Py_False; - PyObject *pruled=Py_False; - PyObject *pclosed=Py_False; - if (!PyArg_ParseTuple(args, "O|O!O!O!", &pcObj, - &(PyBool_Type), &psolid, - &(PyBool_Type), &pruled, - &(PyBool_Type), &pclosed)) { - Base::Console().Message("Part.makeLoft Parameter Error\n"); - return NULL; - } - - try { - TopTools_ListOfShape profiles; - Py::Sequence list(pcObj); - - for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) { - const TopoDS_Shape& sh = static_cast((*it).ptr())-> - getTopoShapePtr()->_Shape; - profiles.Append(sh); - } - } - - TopoShape myShape; - Standard_Boolean anIsSolid = PyObject_IsTrue(psolid) ? Standard_True : Standard_False; - Standard_Boolean anIsRuled = PyObject_IsTrue(pruled) ? Standard_True : Standard_False; - Standard_Boolean anIsClosed = PyObject_IsTrue(pclosed) ? Standard_True : Standard_False; - TopoDS_Shape aResult = myShape.makeLoft(profiles, anIsSolid, anIsRuled,anIsClosed); - return new TopoShapePy(new TopoShape(aResult)); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - Base::Console().Message("debug: Part.makeLoft catching 'Standard_Failure' msg: '%s'\n", e->GetMessageString()); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } - PY_CATCH; -#endif -} - -static PyObject* setStaticValue(PyObject *self, PyObject *args) -{ - char *name, *cval; - if (PyArg_ParseTuple(args, "ss", &name, &cval)) { - if (!Interface_Static::SetCVal(name, cval)) { - PyErr_Format(PyExc_RuntimeError, "Failed to set '%s'", name); - return 0; - } - Py_Return; - } - - PyErr_Clear(); - PyObject* index_or_value; - if (PyArg_ParseTuple(args, "sO", &name, &index_or_value)) { - if (PyInt_Check(index_or_value)) { - int ival = (int)PyInt_AsLong(index_or_value); - if (!Interface_Static::SetIVal(name, ival)) { - PyErr_Format(PyExc_RuntimeError, "Failed to set '%s'", name); - return 0; - } - Py_Return; - } - else if (PyFloat_Check(index_or_value)) { - double rval = PyFloat_AsDouble(index_or_value); - if (!Interface_Static::SetRVal(name, rval)) { - PyErr_Format(PyExc_RuntimeError, "Failed to set '%s'", name); - return 0; - } - Py_Return; - } - } - - PyErr_SetString(PyExc_TypeError, "First argument must be string and must be either string, int or float"); - return 0; -} - -static PyObject * exportUnits(PyObject *self, PyObject *args) -{ - char* unit=0; - if (!PyArg_ParseTuple(args, "|s", &unit)) - return NULL; - if (unit) { - if (strcmp(unit,"M") == 0 || strcmp(unit,"MM") == 0 || strcmp(unit,"IN") == 0) { - if (!Interface_Static::SetCVal("write.iges.unit",unit)) { - PyErr_SetString(PyExc_RuntimeError, "Failed to set 'write.iges.unit'"); - return 0; - } - if (!Interface_Static::SetCVal("write.step.unit",unit)) { - PyErr_SetString(PyExc_RuntimeError, "Failed to set 'write.step.unit'"); - return 0; - } - } - else { - PyErr_SetString(PyExc_ValueError, "Wrong unit"); - return 0; - } - } - - Py::Dict dict; - dict.setItem("write.iges.unit", Py::String(Interface_Static::CVal("write.iges.unit"))); - dict.setItem("write.step.unit", Py::String(Interface_Static::CVal("write.step.unit"))); - return Py::new_reference_to(dict); -} - -static PyObject * toPythonOCC(PyObject *self, PyObject *args) -{ - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj)) - return NULL; - - try { - TopoDS_Shape* shape = new TopoDS_Shape(); - (*shape) = static_cast(pcObj)->getTopoShapePtr()->_Shape; - PyObject* proxy = 0; - proxy = Base::Interpreter().createSWIGPointerObj("OCC.TopoDS", "TopoDS_Shape *", (void*)shape, 1); - return proxy; - } - catch (const Base::Exception& e) { - PyErr_SetString(PartExceptionOCCError, e.what()); - return NULL; - } -} - -static PyObject * fromPythonOCC(PyObject *self, PyObject *args) -{ - PyObject *proxy; - if (!PyArg_ParseTuple(args, "O", &proxy)) - return NULL; - - void* ptr; - try { - TopoShape* shape = new TopoShape(); - Base::Interpreter().convertSWIGPointerObj("OCC.TopoDS","TopoDS_Shape *", proxy, &ptr, 0); - TopoDS_Shape* s = reinterpret_cast(ptr); - shape->_Shape = (*s); - return new TopoShapePy(shape); - } - catch (const Base::Exception& e) { - PyErr_SetString(PartExceptionOCCError, e.what()); - return NULL; - } -} - namespace Part { struct EdgePoints { gp_Pnt v1, v2; @@ -1567,15 +225,1401 @@ static std::list sort_Edges(double tol3d, const std::vector { - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - PyErr_SetString(PartExceptionOCCError, "list of edges expected"); - return 0; +public: + Module() : Py::ExtensionModule("Part") + { + add_varargs_method("open",&Module::open, + "open(string) -- Create a new document and load the file into the document." + ); + add_varargs_method("insert",&Module::insert, + "insert(string,string) -- Insert the file into the given document." + ); + add_varargs_method("export",&Module::exporter, + "export(list,string) -- Export a list of objects into a single file." + ); + add_varargs_method("read",&Module::read, + "read(string) -- Load the file and return the shape." + ); + add_varargs_method("show",&Module::show, + "show(shape) -- Add the shape to the active document or create one if no document exists." + ); + add_varargs_method("makeCompound",&Module::makeCompound, + "makeCompound(list) -- Create a compound out of a list of shapes." + ); + add_varargs_method("makeShell",&Module::makeShell, + "makeShell(list) -- Create a shell out of a list of faces." + ); + add_varargs_method("makeFilledFace",&Module::makeFilledFace, + "makeFilledFace(list) -- Create a face out of a list of edges." + ); + add_varargs_method("makeSolid",&Module::makeSolid, + "makeSolid(shape) -- Create a solid out of the shells inside a shape." + ); + add_varargs_method("makePlane",&Module::makePlane, + "makePlane(length,width,[pnt,dirZ,dirX]) -- Make a plane\n" + "By default pnt=Vector(0,0,0) and dirZ=Vector(0,0,1), dirX is ignored in this case" + ); + add_varargs_method("makeBox",&Module::makeBox, + "makeBox(length,width,height,[pnt,dir]) -- Make a box located\n" + "in pnt with the dimensions (length,width,height)\n" + "By default pnt=Vector(0,0,0) and dir=Vector(0,0,1)" + ); + add_varargs_method("makeWedge",&Module::makeWedge, + "makeWedge(xmin, ymin, zmin, z2min, x2min,\n" + "xmax, ymax, zmax, z2max, x2max,[pnt,dir])\n" + " -- Make a wedge located in pnt\n" + "By default pnt=Vector(0,0,0) and dir=Vector(0,0,1)" + ); + add_varargs_method("makeLine",&Module::makeLine, + "makeLine((x1,y1,z1),(x2,y2,z2)) -- Make a line of two points" + ); + add_varargs_method("makePolygon",&Module::makePolygon, + "makePolygon(list) -- Make a polygon of a list of points" + ); + add_varargs_method("makeCircle",&Module::makeCircle, + "makeCircle(radius,[pnt,dir,angle1,angle2]) -- Make a circle with a given radius\n" + "By default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0 and angle2=360" + ); + add_varargs_method("makeSphere",&Module::makeSphere, + "makeSphere(radius,[pnt, dir, angle1,angle2,angle3]) -- Make a sphere with a given radius\n" + "By default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0, angle2=90 and angle3=360" + ); + add_varargs_method("makeCylinder",&Module::makeCylinder, + "makeCylinder(radius,height,[pnt,dir,angle]) -- Make a cylinder with a given radius and height\n" + "By default pnt=Vector(0,0,0),dir=Vector(0,0,1) and angle=360" + ); + add_varargs_method("makeCone",&Module::makeCone, + "makeCone(radius1,radius2,height,[pnt,dir,angle]) -- Make a cone with given radii and height\n" + "By default pnt=Vector(0,0,0), dir=Vector(0,0,1) and angle=360" + ); + add_varargs_method("makeTorus",&Module::makeTorus, + "makeTorus(radius1,radius2,[pnt,dir,angle1,angle2,angle]) -- Make a torus with a given radii and angles\n" + "By default pnt=Vector(0,0,0),dir=Vector(0,0,1),angle1=0,angle1=360 and angle=360" + ); + add_varargs_method("makeHelix",&Module::makeHelix, + "makeHelix(pitch,height,radius,[angle]) -- Make a helix with a given pitch, height and radius\n" + "By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n" + "(the apex given in degree) a conical surface is used instead" + ); + add_varargs_method("makeLongHelix",&Module::makeLongHelix, + "makeLongHelix(pitch,height,radius,[angle],[hand]) -- Make a (multi-edge) helix with a given pitch, height and radius\n" + "By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n" + "(the apex given in degree) a conical surface is used instead." + ); + add_varargs_method("makeThread",&Module::makeThread, + "makeThread(pitch,depth,height,radius) -- Make a thread with a given pitch, depth, height and radius" + ); + add_varargs_method("makeRevolution",&Module::makeRevolution, + "makeRevolution(Curve,[vmin,vmax,angle,pnt,dir,shapetype]) -- Make a revolved shape\n" + "by rotating the curve or a portion of it around an axis given by (pnt,dir).\n" + "By default vmin/vmax=bounds of the curve,angle=360,pnt=Vector(0,0,0) and\n" + "dir=Vector(0,0,1) and shapetype=Part.Solid" + ); + add_varargs_method("makeRuledSurface",&Module::makeRuledSurface, + "makeRuledSurface(Edge|Wire,Edge|Wire) -- Make a ruled surface\n" + "Create a ruled surface out of two edges or wires. If wires are used then" + "these must have the same number of edges." + ); + add_varargs_method("makeTube",&Module::makeTube, + "makeTube(edge,radius,[continuity,max degree,max segments]) -- Create a tube.\n" + "continuity is a string which must be 'C0','C1','C2','C3','CN','G1' or 'G1'," + ); + add_varargs_method("makeSweepSurface",&Module::makeSweepSurface, + "makeSweepSurface(edge(path),edge(profile),[float]) -- Create a profile along a path." + ); + add_varargs_method("makeLoft",&Module::makeLoft, + "makeLoft(list of wires,[solid=False,ruled=False,closed=False]) -- Create a loft shape." + ); + add_varargs_method("makeWireString",&Module::makeWireString, + "makeWireString(string,fontdir,fontfile,height,[track]) -- Make list of wires in the form of a string's characters." + ); + add_varargs_method("exportUnits",&Module::exportUnits, + "exportUnits([string=MM|M|IN]) -- Set units for exporting STEP/IGES files and returns the units." + ); + add_varargs_method("setStaticValue",&Module::setStaticValue, + "setStaticValue(string,string|int|float) -- Set a name to a value The value can be a string, int or float." + ); + add_varargs_method("cast_to_shape",&Module::cast_to_shape, + "cast_to_shape(shape) -- Cast to the actual shape type" + ); + add_varargs_method("getSortedClusters",&Module::getSortedClusters, + "getSortedClusters(list of edges) -- Helper method to sort and cluster a variety of edges" + ); + add_varargs_method("__sortEdges__",&Module::sortEdges, + "__sortEdges__(list of edges) -- Helper method to sort an unsorted list of edges so that afterwards\n" + "two adjacent edges share a common vertex" + ); + add_varargs_method("__toPythonOCC__",&Module::toPythonOCC, + "__toPythonOCC__(shape) -- Helper method to convert an internal shape to pythonocc shape" + ); + add_varargs_method("__fromPythonOCC__",&Module::fromPythonOCC, + "__fromPythonOCC__(occ) -- Helper method to convert a pythonocc shape to an internal shape" + ); + initialize("This is a module working with shapes."); // register with Python } - PY_TRY { + virtual ~Module() {} + +private: + virtual Py::Object invoke_method_varargs(void *method_def, const Py::Tuple &args) + { + try { + return Py::ExtensionModule::invoke_method_varargs(method_def, args); + } + catch (const Standard_Failure &e) { + std::string str; + Standard_CString msg = e.GetMessageString(); + str += typeid(e).name(); + str += " "; + if (msg) {str += msg;} + else {str += "No OCCT Exception Message";} + Base::Console().Error("%s\n", str.c_str()); + throw Py::Exception(Part::PartExceptionOCCError, str); + } + catch (const Base::Exception &e) { + std::string str; + str += "FreeCAD exception thrown ("; + str += e.what(); + str += ")"; + e.ReportException(); + throw Py::RuntimeError(str); + } + catch (const std::exception &e) { + std::string str; + str += "C++ exception thrown ("; + str += e.what(); + str += ")"; + Base::Console().Error("%s\n", str.c_str()); + throw Py::RuntimeError(str); + } + } + + Py::Object open(const Py::Tuple& args) + { + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name)) + throw Py::Exception(); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + //Base::Console().Log("Open in Part with %s",Name); + Base::FileInfo file(EncodedName.c_str()); + + // extract ending + if (file.extension().empty()) + throw Py::RuntimeError("No file extension"); + + if (file.hasExtension("stp") || file.hasExtension("step")) { + // create new document and add Import feature + App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); +#if 1 + ImportStepParts(pcDoc,EncodedName.c_str()); +#else + Part::ImportStep *pcFeature = (Part::ImportStep *)pcDoc->addObject("Part::ImportStep",file.fileNamePure().c_str()); + pcFeature->FileName.setValue(Name); +#endif + pcDoc->recompute(); + } +#if 1 + else if (file.hasExtension("igs") || file.hasExtension("iges")) { + App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); + ImportIgesParts(pcDoc,EncodedName.c_str()); + pcDoc->recompute(); + } +#endif + else { + TopoShape shape; + shape.read(EncodedName.c_str()); + + // create new document set loaded shape + App::Document *pcDoc = App::GetApplication().newDocument(file.fileNamePure().c_str()); + Part::Feature *object = static_cast(pcDoc->addObject + ("Part::Feature",file.fileNamePure().c_str())); + object->Shape.setValue(shape); + pcDoc->recompute(); + } + + return Py::None(); + } + Py::Object insert(const Py::Tuple& args) + { + char* Name; + const char* DocName; + if (!PyArg_ParseTuple(args.ptr(), "ets","utf-8",&Name,&DocName)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + //Base::Console().Log("Insert in Part with %s",Name); + Base::FileInfo file(EncodedName.c_str()); + + // extract ending + if (file.extension().empty()) + throw Py::RuntimeError("No file extension"); + + App::Document *pcDoc = App::GetApplication().getDocument(DocName); + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument(DocName); + } + + if (file.hasExtension("stp") || file.hasExtension("step")) { +#if 1 + ImportStepParts(pcDoc,EncodedName.c_str()); +#else + // add Import feature + Part::ImportStep *pcFeature = (Part::ImportStep *)pcDoc->addObject("Part::ImportStep",file.fileNamePure().c_str()); + pcFeature->FileName.setValue(Name); +#endif + pcDoc->recompute(); + } +#if 1 + else if (file.hasExtension("igs") || file.hasExtension("iges")) { + ImportIgesParts(pcDoc,EncodedName.c_str()); + pcDoc->recompute(); + } +#endif + else { + TopoShape shape; + shape.read(EncodedName.c_str()); + + Part::Feature *object = static_cast(pcDoc->addObject + ("Part::Feature",file.fileNamePure().c_str())); + object->Shape.setValue(shape); + pcDoc->recompute(); + } + + return Py::None(); + } + Py::Object exporter(const Py::Tuple& args) + { + PyObject* object; + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "Oet",&object,"utf-8",&Name)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + BRep_Builder builder; + TopoDS_Compound comp; + builder.MakeCompound(comp); + + Py::Sequence list(object); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + PyObject* item = (*it).ptr(); + if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) { + App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr(); + if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { + Part::Feature* part = static_cast(obj); + const TopoDS_Shape& shape = part->Shape.getValue(); + if (!shape.IsNull()) + builder.Add(comp, shape); + } + else { + Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue()); + } + } + } + + TopoShape shape(comp); + shape.write(EncodedName.c_str()); + + return Py::None(); + } + Py::Object read(const Py::Tuple& args) + { + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + TopoShape* shape = new TopoShape(); + shape->read(EncodedName.c_str()); + return Py::asObject(new TopoShapePy(shape)); + } + Py::Object show(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O!", &(TopoShapePy::Type), &pcObj)) + throw Py::Exception(); + + App::Document *pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(); + TopoShapePy* pShape = static_cast(pcObj); + Part::Feature *pcFeature = (Part::Feature *)pcDoc->addObject("Part::Feature", "Shape"); + // copy the data + //TopoShape* shape = new MeshObject(*pShape->getTopoShapeObjectPtr()); + pcFeature->Shape.setValue(pShape->getTopoShapePtr()->_Shape); + pcDoc->recompute(); + + return Py::None(); + } + Py::Object makeCompound(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O", &pcObj)) + throw Py::Exception(); + + BRep_Builder builder; + TopoDS_Compound Comp; + builder.MakeCompound(Comp); + + try { + Py::Sequence list(pcObj); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) { + const TopoDS_Shape& sh = static_cast((*it).ptr())-> + getTopoShapePtr()->_Shape; + if (!sh.IsNull()) + builder.Add(Comp, sh); + } + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + + return Py::asObject(new TopoShapeCompoundPy(new TopoShape(Comp))); + } + Py::Object makeShell(const Py::Tuple& args) + { + PyObject *obj; + if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) + throw Py::Exception(); + + BRep_Builder builder; + TopoDS_Shape shape; + TopoDS_Shell shell; + //BRepOffsetAPI_Sewing mkShell; + builder.MakeShell(shell); + + try { + Py::Sequence list(obj); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapeFacePy::Type))) { + const TopoDS_Shape& sh = static_cast((*it).ptr())-> + getTopoShapePtr()->_Shape; + if (!sh.IsNull()) + builder.Add(shell, sh); + } + } + + shape = shell; + BRepCheck_Analyzer check(shell); + if (!check.IsValid()) { + ShapeUpgrade_ShellSewing sewShell; + shape = sewShell.ApplySewing(shell); + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + + return Py::asObject(new TopoShapeShellPy(new TopoShape(shape))); + } + Py::Object makeFilledFace(const Py::Tuple& args) + { + // TODO: BRepFeat_SplitShape + PyObject *obj; + PyObject *surf=0; + if (!PyArg_ParseTuple(args.ptr(), "O|O!", &obj, &TopoShapeFacePy::Type, &surf)) + throw Py::Exception(); + + // See also BRepOffsetAPI_MakeFilling + BRepFill_Filling builder; + try { + if (surf) { + const TopoDS_Shape& face = static_cast(surf)-> + getTopoShapePtr()->_Shape; + if (!face.IsNull() && face.ShapeType() == TopAbs_FACE) { + builder.LoadInitSurface(TopoDS::Face(face)); + } + } + Py::Sequence list(obj); + int numConstraints = 0; + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) { + const TopoDS_Shape& sh = static_cast((*it).ptr())-> + getTopoShapePtr()->_Shape; + if (!sh.IsNull()) { + if (sh.ShapeType() == TopAbs_EDGE) { + builder.Add(TopoDS::Edge(sh), GeomAbs_C0); + numConstraints++; + } + else if (sh.ShapeType() == TopAbs_FACE) { + builder.Add(TopoDS::Face(sh), GeomAbs_C0); + numConstraints++; + } + else if (sh.ShapeType() == TopAbs_VERTEX) { + const TopoDS_Vertex& v = TopoDS::Vertex(sh); + gp_Pnt pnt = BRep_Tool::Pnt(v); + builder.Add(pnt); + numConstraints++; + } + } + } + } + + if (numConstraints == 0) { + throw Py::Exception(PartExceptionOCCError, "Failed to created face with no constraints"); + } + + builder.Build(); + if (builder.IsDone()) { + return Py::asObject(new TopoShapeFacePy(new TopoShape(builder.Face()))); + } + else { + throw Py::Exception(PartExceptionOCCError, "Failed to created face by filling edges"); + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + } + Py::Object makeSolid(const Py::Tuple& args) + { + PyObject *obj; + if (!PyArg_ParseTuple(args.ptr(), "O!", &(TopoShapePy::Type), &obj)) + throw Py::Exception(); + + try { + BRepBuilderAPI_MakeSolid mkSolid; + const TopoDS_Shape& shape = static_cast(obj) + ->getTopoShapePtr()->_Shape; + TopExp_Explorer anExp (shape, TopAbs_SHELL); + int count=0; + for (; anExp.More(); anExp.Next()) { + ++count; + mkSolid.Add(TopoDS::Shell(anExp.Current())); + } + + if (count == 0) + Standard_Failure::Raise("No shells found in shape"); + + TopoDS_Solid solid = mkSolid.Solid(); + BRepLib::OrientClosedSolid(solid); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(solid))); + } + catch (Standard_Failure) { + throw Py::Exception(PartExceptionOCCError, "creation of solid failed"); + } + } + Py::Object makePlane(const Py::Tuple& args) + { + double length, width; + PyObject *pPnt=0, *pDirZ=0, *pDirX=0; + if (!PyArg_ParseTuple(args.ptr(), "dd|O!O!O!", &length, &width, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDirZ, + &(Base::VectorPy::Type), &pDirX)) + throw Py::Exception(); + + if (length < Precision::Confusion()) { + throw Py::ValueError("length of plane too small"); + } + if (width < Precision::Confusion()) { + throw Py::ValueError("width of plane too small"); + } + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDirZ) { + Base::Vector3d vec = static_cast(pDirZ)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + Handle_Geom_Plane aPlane; + if (pDirX) { + Base::Vector3d vec = static_cast(pDirX)->value(); + gp_Dir dx; + dx.SetCoord(vec.x, vec.y, vec.z); + aPlane = new Geom_Plane(gp_Ax3(p, d, dx)); + } + else { + aPlane = new Geom_Plane(p, d); + } + + BRepBuilderAPI_MakeFace Face(aPlane, 0.0, length, 0.0, width +#if OCC_VERSION_HEX >= 0x060502 + , Precision::Confusion() +#endif + ); + return Py::asObject(new TopoShapeFacePy(new TopoShape((Face.Face())))); + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of plane failed"); + } + catch (Standard_Failure) { + throw Py::Exception(PartExceptionOCCError, "creation of plane failed"); + } + } + Py::Object makeBox(const Py::Tuple& args) + { + double length, width, height; + PyObject *pPnt=0, *pDir=0; + if (!PyArg_ParseTuple(args.ptr(), "ddd|O!O!", + &length, &width, &height, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir)) + throw Py::Exception(); + + if (length < Precision::Confusion()) { + throw Py::ValueError("length of box too small"); + } + if (width < Precision::Confusion()) { + throw Py::ValueError("width of box too small"); + } + if (height < Precision::Confusion()) { + throw Py::ValueError("height of box too small"); + } + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + BRepPrimAPI_MakeBox mkBox(gp_Ax2(p,d), length, width, height); + TopoDS_Shape ResultShape = mkBox.Shape(); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(ResultShape))); + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of box failed"); + } + } + Py::Object makeWedge(const Py::Tuple& args) + { + double xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max; + PyObject *pPnt=0, *pDir=0; + if (!PyArg_ParseTuple(args.ptr(), "dddddddddd|O!O!", + &xmin, &ymin, &zmin, &z2min, &x2min, &xmax, &ymax, &zmax, &z2max, &x2max, + &(Base::VectorPy::Type), &pPnt, &(Base::VectorPy::Type), &pDir)) + throw Py::Exception(); + + double dx = xmax-xmin; + double dy = ymax-ymin; + double dz = zmax-zmin; + double dz2 = z2max-z2min; + double dx2 = x2max-x2min; + if (dx < Precision::Confusion()) { + throw Py::ValueError("delta x of wedge too small"); + } + if (dy < Precision::Confusion()) { + throw Py::ValueError("delta y of wedge too small"); + } + if (dz < Precision::Confusion()) { + throw Py::ValueError("delta z of wedge too small"); + } + if (dz2 < 0) { + throw Py::ValueError("delta z2 of wedge is negative"); + } + if (dx2 < 0) { + throw Py::ValueError("delta x2 of wedge is negative"); + } + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + BRepPrim_Wedge mkWedge(gp_Ax2(p,d), xmin, ymin, zmin, z2min, x2min, xmax, ymax, zmax, z2max, x2max); + BRepBuilderAPI_MakeSolid mkSolid; + mkSolid.Add(mkWedge.Shell()); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(mkSolid.Solid()))); + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of wedge failed"); + } + } + Py::Object makeLine(const Py::Tuple& args) + { + PyObject *obj1, *obj2; + if (!PyArg_ParseTuple(args.ptr(), "OO", &obj1, &obj2)) + throw Py::Exception(); + + Base::Vector3d pnt1, pnt2; + if (PyObject_TypeCheck(obj1, &(Base::VectorPy::Type))) { + pnt1 = static_cast(obj1)->value(); + } + else if (PyObject_TypeCheck(obj1, &PyTuple_Type)) { + pnt1 = Base::getVectorFromTuple(obj1); + } + else { + throw Py::TypeError("first argument must either be vector or tuple"); + } + if (PyObject_TypeCheck(obj2, &(Base::VectorPy::Type))) { + pnt2 = static_cast(obj2)->value(); + } + else if (PyObject_TypeCheck(obj2, &PyTuple_Type)) { + pnt2 = Base::getVectorFromTuple(obj2); + } + else { + throw Py::TypeError("second argument must either be vector or tuple"); + } + + // Create directly the underlying line geometry + BRepBuilderAPI_MakeEdge makeEdge(gp_Pnt(pnt1.x, pnt1.y, pnt1.z), + gp_Pnt(pnt2.x, pnt2.y, pnt2.z)); + + const char *error=0; + switch (makeEdge.Error()) + { + case BRepBuilderAPI_EdgeDone: + break; // ok + case BRepBuilderAPI_PointProjectionFailed: + error = "Point projection failed"; + break; + case BRepBuilderAPI_ParameterOutOfRange: + error = "Parameter out of range"; + break; + case BRepBuilderAPI_DifferentPointsOnClosedCurve: + error = "Different points on closed curve"; + break; + case BRepBuilderAPI_PointWithInfiniteParameter: + error = "Point with infinite parameter"; + break; + case BRepBuilderAPI_DifferentsPointAndParameter: + error = "Different point and parameter"; + break; + case BRepBuilderAPI_LineThroughIdenticPoints: + error = "Line through identic points"; + break; + } + // Error + if (error) { + throw Py::Exception(PartExceptionOCCError, error); + } + + TopoDS_Edge edge = makeEdge.Edge(); + return Py::asObject(new TopoShapeEdgePy(new TopoShape(edge))); + } + Py::Object makePolygon(const Py::Tuple& args) + { + PyObject *pcObj; + PyObject *pclosed=Py_False; + if (!PyArg_ParseTuple(args.ptr(), "O|O!", &pcObj, &(PyBool_Type), &pclosed)) + throw Py::Exception(); + + BRepBuilderAPI_MakePolygon mkPoly; + try { + Py::Sequence list(pcObj); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + if (PyObject_TypeCheck((*it).ptr(), &(Base::VectorPy::Type))) { + Base::Vector3d v = static_cast((*it).ptr())->value(); + mkPoly.Add(gp_Pnt(v.x,v.y,v.z)); + } + else if (PyObject_TypeCheck((*it).ptr(), &PyTuple_Type)) { + Base::Vector3d v = Base::getVectorFromTuple((*it).ptr()); + mkPoly.Add(gp_Pnt(v.x,v.y,v.z)); + } + } + + if (!mkPoly.IsDone()) + Standard_Failure::Raise("Cannot create polygon because less than two vertices are given"); + + // if the polygon should be closed + if (PyObject_IsTrue(pclosed)) { + if (!mkPoly.FirstVertex().IsSame(mkPoly.LastVertex())) { + mkPoly.Add(mkPoly.FirstVertex()); + } + } + + return Py::asObject(new TopoShapeWirePy(new TopoShape(mkPoly.Wire()))); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + } + Py::Object makeCircle(const Py::Tuple& args) + { + double radius, angle1=0.0, angle2=360; + PyObject *pPnt=0, *pDir=0; + if (!PyArg_ParseTuple(args.ptr(), "d|O!O!dd", + &radius, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir, + &angle1, &angle2)) + throw Py::Exception(); + + try { + gp_Pnt loc(0,0,0); + gp_Dir dir(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + loc.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + dir.SetCoord(vec.x, vec.y, vec.z); + } + gp_Ax1 axis(loc, dir); + gp_Circ circle; + circle.SetAxis(axis); + circle.SetRadius(radius); + + Handle_Geom_Circle hCircle = new Geom_Circle (circle); + BRepBuilderAPI_MakeEdge aMakeEdge(hCircle, angle1*(M_PI/180), angle2*(M_PI/180)); + TopoDS_Edge edge = aMakeEdge.Edge(); + return Py::asObject(new TopoShapeEdgePy(new TopoShape(edge))); + } + catch (Standard_Failure) { + throw Py::Exception(PartExceptionOCCError, "creation of circle failed"); + } + } + Py::Object makeSphere(const Py::Tuple& args) + { + double radius, angle1=-90, angle2=90, angle3=360; + PyObject *pPnt=0, *pDir=0; + if (!PyArg_ParseTuple(args.ptr(), "d|O!O!ddd", + &radius, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir, + &angle1, &angle2, &angle3)) + throw Py::Exception(); + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + BRepPrimAPI_MakeSphere mkSphere(gp_Ax2(p,d), radius, angle1*(M_PI/180), angle2*(M_PI/180), angle3*(M_PI/180)); + TopoDS_Shape shape = mkSphere.Shape(); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape))); + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of sphere failed"); + } + } + Py::Object makeCylinder(const Py::Tuple& args) + { + double radius, height, angle=360; + PyObject *pPnt=0, *pDir=0; + if (!PyArg_ParseTuple(args.ptr(), "dd|O!O!d", + &radius, &height, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir, + &angle)) + throw Py::Exception(); + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + BRepPrimAPI_MakeCylinder mkCyl(gp_Ax2(p,d),radius, height, angle*(M_PI/180)); + TopoDS_Shape shape = mkCyl.Shape(); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape))); + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of cylinder failed"); + } + } + Py::Object makeCone(const Py::Tuple& args) + { + double radius1, radius2, height, angle=360; + PyObject *pPnt=0, *pDir=0; + if (!PyArg_ParseTuple(args.ptr(), "ddd|O!O!d", + &radius1, &radius2, &height, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir, + &angle)) + throw Py::Exception(); + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + BRepPrimAPI_MakeCone mkCone(gp_Ax2(p,d),radius1, radius2, height, angle*(M_PI/180)); + TopoDS_Shape shape = mkCone.Shape(); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape))); + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of cone failed"); + } + } + Py::Object makeTorus(const Py::Tuple& args) + { + double radius1, radius2, angle1=0.0, angle2=360, angle=360; + PyObject *pPnt=0, *pDir=0; + if (!PyArg_ParseTuple(args.ptr(), "dd|O!O!ddd", + &radius1, &radius2, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir, + &angle1, &angle2, &angle)) + throw Py::Exception(); + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + BRepPrimAPI_MakeTorus mkTorus(gp_Ax2(p,d), radius1, radius2, angle1*(M_PI/180), angle2*(M_PI/180), angle*(M_PI/180)); + const TopoDS_Shape& shape = mkTorus.Shape(); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape))); + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of torus failed"); + } + } + Py::Object makeHelix(const Py::Tuple& args) + { + double pitch, height, radius, angle=-1.0; + PyObject *pleft=Py_False; + PyObject *pvertHeight=Py_False; + if (!PyArg_ParseTuple(args.ptr(), "ddd|dO!O!", + &pitch, &height, &radius, &angle, + &(PyBool_Type), &pleft, + &(PyBool_Type), &pvertHeight)) + throw Py::Exception(); + + try { + TopoShape helix; + Standard_Boolean anIsLeft = PyObject_IsTrue(pleft) ? Standard_True : Standard_False; + Standard_Boolean anIsVertHeight = PyObject_IsTrue(pvertHeight) ? Standard_True : Standard_False; + TopoDS_Shape wire = helix.makeHelix(pitch, height, radius, angle, + anIsLeft, anIsVertHeight); + return Py::asObject(new TopoShapeWirePy(new TopoShape(wire))); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + } + Py::Object makeLongHelix(const Py::Tuple& args) + { + double pitch, height, radius, angle=-1.0; + PyObject *pleft=Py_False; + if (!PyArg_ParseTuple(args.ptr(), "ddd|dO!", &pitch, &height, &radius, &angle, + &(PyBool_Type), &pleft)) { + throw Py::Exception("Part.makeLongHelix fails on parms"); + } + + try { + TopoShape helix; + Standard_Boolean anIsLeft = PyObject_IsTrue(pleft) ? Standard_True : Standard_False; + TopoDS_Shape wire = helix.makeLongHelix(pitch, height, radius, angle, anIsLeft); + return Py::asObject(new TopoShapeWirePy(new TopoShape(wire))); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + } + Py::Object makeThread(const Py::Tuple& args) + { + double pitch, depth, height, radius; + if (!PyArg_ParseTuple(args.ptr(), "dddd", &pitch, &depth, &height, &radius)) + throw Py::Exception(); + + try { + TopoShape helix; + TopoDS_Shape wire = helix.makeThread(pitch, depth, height, radius); + return Py::asObject(new TopoShapeWirePy(new TopoShape(wire))); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + } + Py::Object makeRevolution(const Py::Tuple& args) + { + double vmin = DBL_MAX, vmax=-DBL_MAX; + double angle=360; + PyObject *pPnt=0, *pDir=0, *pCrv; + Handle_Geom_Curve curve; + union PyType_Object defaultType = {&Part::TopoShapeSolidPy::Type}; + PyObject* type = defaultType.o; + if (PyArg_ParseTuple(args.ptr(), "O!|dddO!O!O!", &(GeometryPy::Type), &pCrv, + &vmin, &vmax, &angle, + &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir, + &(PyType_Type), &type)) { + GeometryPy* pcGeo = static_cast(pCrv); + curve = Handle_Geom_Curve::DownCast + (pcGeo->getGeometryPtr()->handle()); + if (curve.IsNull()) { + throw Py::Exception(PyExc_TypeError, "geometry is not a curve"); + } + if (vmin == DBL_MAX) + vmin = curve->FirstParameter(); + + if (vmax == -DBL_MAX) + vmax = curve->LastParameter(); + } + else { + PyErr_Clear(); + if (!PyArg_ParseTuple(args.ptr(), "O!|dddO!O!", &(TopoShapePy::Type), &pCrv, + &vmin, &vmax, &angle, &(Base::VectorPy::Type), &pPnt, + &(Base::VectorPy::Type), &pDir)) { + throw Py::Exception(); + } + const TopoDS_Shape& shape = static_cast(pCrv)->getTopoShapePtr()->_Shape; + if (shape.IsNull()) { + throw Py::Exception(PartExceptionOCCError, "shape is empty"); + } + + if (shape.ShapeType() != TopAbs_EDGE) { + throw Py::Exception(PartExceptionOCCError, "shape is not an edge"); + } + + const TopoDS_Edge& edge = TopoDS::Edge(shape); + BRepAdaptor_Curve adapt(edge); + + const Handle_Geom_Curve& hCurve = adapt.Curve().Curve(); + // Apply placement of the shape to the curve + TopLoc_Location loc = edge.Location(); + curve = Handle_Geom_Curve::DownCast(hCurve->Transformed(loc.Transformation())); + if (curve.IsNull()) { + throw Py::Exception(PartExceptionOCCError, "invalid curve in edge"); + } + + if (vmin == DBL_MAX) + vmin = adapt.FirstParameter(); + if (vmax == -DBL_MAX) + vmax = adapt.LastParameter(); + } + + try { + gp_Pnt p(0,0,0); + gp_Dir d(0,0,1); + if (pPnt) { + Base::Vector3d pnt = static_cast(pPnt)->value(); + p.SetCoord(pnt.x, pnt.y, pnt.z); + } + if (pDir) { + Base::Vector3d vec = static_cast(pDir)->value(); + d.SetCoord(vec.x, vec.y, vec.z); + } + + union PyType_Object shellType = {&Part::TopoShapeShellPy::Type}; + union PyType_Object faceType = {&Part::TopoShapeFacePy::Type}; + + BRepPrimAPI_MakeRevolution mkRev(gp_Ax2(p,d),curve, vmin, vmax, angle*(M_PI/180)); + if (type == defaultType.o) { + TopoDS_Shape shape = mkRev.Solid(); + return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape))); + } + else if (type == shellType.o) { + TopoDS_Shape shape = mkRev.Shell(); + return Py::asObject(new TopoShapeShellPy(new TopoShape(shape))); + } + else if (type == faceType.o) { + TopoDS_Shape shape = mkRev.Face(); + return Py::asObject(new TopoShapeFacePy(new TopoShape(shape))); + } + else { + TopoDS_Shape shape = mkRev.Shape(); + return Py::asObject(new TopoShapePy(new TopoShape(shape))); + } + } + catch (Standard_DomainError) { + throw Py::Exception(PartExceptionOCCDomainError, "creation of revolved shape failed"); + } + } + Py::Object makeRuledSurface(const Py::Tuple& args) + { + // http://opencascade.blogspot.com/2009/10/surface-modeling-part1.html + PyObject *sh1, *sh2; + if (!PyArg_ParseTuple(args.ptr(), "O!O!", &(TopoShapePy::Type), &sh1, + &(TopoShapePy::Type), &sh2)) + throw Py::Exception(); + + const TopoDS_Shape& shape1 = static_cast(sh1)->getTopoShapePtr()->_Shape; + const TopoDS_Shape& shape2 = static_cast(sh2)->getTopoShapePtr()->_Shape; + + try { + if (shape1.ShapeType() == TopAbs_EDGE && shape2.ShapeType() == TopAbs_EDGE) { + TopoDS_Face face = BRepFill::Face(TopoDS::Edge(shape1), TopoDS::Edge(shape2)); + return Py::asObject(new TopoShapeFacePy(new TopoShape(face))); + } + else if (shape1.ShapeType() == TopAbs_WIRE && shape2.ShapeType() == TopAbs_WIRE) { + TopoDS_Shell shell = BRepFill::Shell(TopoDS::Wire(shape1), TopoDS::Wire(shape2)); + return Py::asObject(new TopoShapeShellPy(new TopoShape(shell))); + } + else { + throw Py::Exception(PartExceptionOCCError, "curves must either be edges or wires"); + } + } + catch (Standard_Failure) { + throw Py::Exception(PartExceptionOCCError, "creation of ruled surface failed"); + } + } + Py::Object makeTube(const Py::Tuple& args) + { + PyObject *pshape; + double radius; + double tolerance=0.001; + char* scont = "C0"; + int maxdegree = 3; + int maxsegment = 30; + + // Path + radius + if (!PyArg_ParseTuple(args.ptr(), "O!d|sii", &(TopoShapePy::Type), &pshape, &radius, &scont, &maxdegree, &maxsegment)) + throw Py::Exception(); + + std::string str_cont = scont; + int cont; + if (str_cont == "C0") + cont = (int)GeomAbs_C0; + else if (str_cont == "C1") + cont = (int)GeomAbs_C1; + else if (str_cont == "C2") + cont = (int)GeomAbs_C2; + else if (str_cont == "C3") + cont = (int)GeomAbs_C3; + else if (str_cont == "CN") + cont = (int)GeomAbs_CN; + else if (str_cont == "G1") + cont = (int)GeomAbs_G1; + else if (str_cont == "G2") + cont = (int)GeomAbs_G2; + else + cont = (int)GeomAbs_C0; + + try { + const TopoDS_Shape& path_shape = static_cast(pshape)->getTopoShapePtr()->_Shape; + TopoShape myShape(path_shape); + TopoDS_Shape face = myShape.makeTube(radius, tolerance, cont, maxdegree, maxsegment); + return Py::asObject(new TopoShapeFacePy(new TopoShape(face))); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + } + Py::Object makeSweepSurface(const Py::Tuple& args) + { + PyObject *path, *profile; + double tolerance=0.001; + int fillMode = 0; + + // Path + profile + if (!PyArg_ParseTuple(args.ptr(), "O!O!|di", &(TopoShapePy::Type), &path, + &(TopoShapePy::Type), &profile, + &tolerance, &fillMode)) + throw Py::Exception(); + + try { + const TopoDS_Shape& path_shape = static_cast(path)->getTopoShapePtr()->_Shape; + const TopoDS_Shape& prof_shape = static_cast(profile)->getTopoShapePtr()->_Shape; + + TopoShape myShape(path_shape); + TopoDS_Shape face = myShape.makeSweep(prof_shape, tolerance, fillMode); + return Py::asObject(new TopoShapeFacePy(new TopoShape(face))); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(PartExceptionOCCError, e->GetMessageString()); + } + } + Py::Object makeLoft(const Py::Tuple& args) + { +#if 0 + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O", &pcObj)) + throw Py::Exception; + + NCollection_List theSections; + Py::Sequence list(pcObj); + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + if (PyObject_TypeCheck((*it).ptr(), &(Part::GeometryCurvePy::Type))) { + Handle_Geom_Curve hCurve = Handle_Geom_Curve::DownCast( + static_cast((*it).ptr())->getGeomCurvePtr()->handle()); + theSections.Append(hCurve); + } + } + + //populate section generator + GeomFill_SectionGenerator aSecGenerator; + for (NCollection_List::Iterator anIt(theSections); anIt.More(); anIt.Next()) { + const Handle_Geom_Curve& aCurve = anIt.Value(); + aSecGenerator.AddCurve (aCurve); + } + aSecGenerator.Perform (Precision::PConfusion()); + + Handle_GeomFill_Line aLine = new GeomFill_Line (theSections.Size()); + + //parameters + const Standard_Integer aMinDeg = 1, aMaxDeg = BSplCLib::MaxDegree(), aNbIt = 0; + Standard_Real aTol3d = 1e-4, aTol2d = Precision::Parametric (aTol3d); + + //algorithm + GeomFill_AppSurf anAlgo (aMinDeg, aMaxDeg, aTol3d, aTol2d, aNbIt); + anAlgo.Perform (aLine, aSecGenerator); + + if (!anAlgo.IsDone()) { + PyErr_SetString(PartExceptionOCCError, "Failed to create loft surface"); + return 0; + } + + Handle_Geom_BSplineSurface aRes; + aRes = new Geom_BSplineSurface(anAlgo.SurfPoles(), anAlgo.SurfWeights(), + anAlgo.SurfUKnots(), anAlgo.SurfVKnots(), anAlgo.SurfUMults(), anAlgo.SurfVMults(), + anAlgo.UDegree(), anAlgo.VDegree()); + return new BSplineSurfacePy(new GeomBSplineSurface(aRes)); +#else + PyObject *pcObj; + PyObject *psolid=Py_False; + PyObject *pruled=Py_False; + PyObject *pclosed=Py_False; + if (!PyArg_ParseTuple(args.ptr(), "O|O!O!O!", &pcObj, + &(PyBool_Type), &psolid, + &(PyBool_Type), &pruled, + &(PyBool_Type), &pclosed)) { + throw Py::Exception(); + } + + TopTools_ListOfShape profiles; + Py::Sequence list(pcObj); + + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { + if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) { + const TopoDS_Shape& sh = static_cast((*it).ptr())-> + getTopoShapePtr()->_Shape; + profiles.Append(sh); + } + } + + TopoShape myShape; + Standard_Boolean anIsSolid = PyObject_IsTrue(psolid) ? Standard_True : Standard_False; + Standard_Boolean anIsRuled = PyObject_IsTrue(pruled) ? Standard_True : Standard_False; + Standard_Boolean anIsClosed = PyObject_IsTrue(pclosed) ? Standard_True : Standard_False; + TopoDS_Shape aResult = myShape.makeLoft(profiles, anIsSolid, anIsRuled,anIsClosed); + return Py::asObject(new TopoShapePy(new TopoShape(aResult))); +#endif + } + Py::Object makeWireString(const Py::Tuple& args) + { +#ifdef FCUseFreeType + PyObject *intext; + const char* dir; + const char* fontfile; + const char* fontspec; + bool useFontSpec = false; + double height; + double track = 0; + + Py_UNICODE *unichars; + Py_ssize_t pysize; + + PyObject *CharList; + + if (PyArg_ParseTuple(args.ptr(), "Ossd|d", &intext, // compatibility with old version + &dir, + &fontfile, + &height, + &track)) { + useFontSpec = false; + } + else { + PyErr_Clear(); + if (PyArg_ParseTuple(args.ptr(), "Osd|d", &intext, + &fontspec, + &height, + &track)) { + useFontSpec = true; + } + else { + throw Py::TypeError("** makeWireString bad args."); + } + } + + if (PyString_Check(intext)) { + PyObject *p = Base::PyAsUnicodeObject(PyString_AsString(intext)); + if (!p) { + throw Py::TypeError("** makeWireString can't convert PyString."); + } + pysize = PyUnicode_GetSize(p); + unichars = PyUnicode_AS_UNICODE(p); + } + else if (PyUnicode_Check(intext)) { + pysize = PyUnicode_GetSize(intext); + unichars = PyUnicode_AS_UNICODE(intext); + } + else { + throw Py::TypeError("** makeWireString bad text parameter"); + } + + try { + if (useFontSpec) { + CharList = FT2FC(unichars,pysize,fontspec,height,track); + } + else { + CharList = FT2FC(unichars,pysize,dir,fontfile,height,track); + } + } + catch (Standard_DomainError) { // Standard_DomainError is OCC error. + throw Py::Exception(PartExceptionOCCDomainError, "makeWireString failed - Standard_DomainError"); + } + catch (std::runtime_error& e) { // FT2 or FT2FC errors + throw Py::Exception(PartExceptionOCCError, e.what()); + } + + return Py::asObject(CharList); +#else + throw Py::RuntimeError("FreeCAD compiled without FreeType support! This method is disabled..."); +#endif + return Py::None(); + } + Py::Object exportUnits(const Py::Tuple& args) + { + char* unit=0; + if (!PyArg_ParseTuple(args.ptr(), "|s", &unit)) + throw Py::Exception(); + + if (unit) { + if (strcmp(unit,"M") == 0 || strcmp(unit,"MM") == 0 || strcmp(unit,"IN") == 0) { + if (!Interface_Static::SetCVal("write.iges.unit",unit)) { + throw Py::RuntimeError("Failed to set 'write.iges.unit'"); + } + if (!Interface_Static::SetCVal("write.step.unit",unit)) { + throw Py::RuntimeError("Failed to set 'write.step.unit'"); + } + } + else { + throw Py::ValueError("Wrong unit"); + } + } + + Py::Dict dict; + dict.setItem("write.iges.unit", Py::String(Interface_Static::CVal("write.iges.unit"))); + dict.setItem("write.step.unit", Py::String(Interface_Static::CVal("write.step.unit"))); + return dict; + } + Py::Object setStaticValue(const Py::Tuple& args) + { + char *name, *cval; + if (PyArg_ParseTuple(args.ptr(), "ss", &name, &cval)) { + if (!Interface_Static::SetCVal(name, cval)) { + std::stringstream str; + str << "Failed to set '" << name << "'"; + throw Py::RuntimeError(str.str()); + } + return Py::None(); + } + + PyErr_Clear(); + PyObject* index_or_value; + if (PyArg_ParseTuple(args.ptr(), "sO", &name, &index_or_value)) { + if (PyInt_Check(index_or_value)) { + int ival = (int)PyInt_AsLong(index_or_value); + if (!Interface_Static::SetIVal(name, ival)) { + std::stringstream str; + str << "Failed to set '" << name << "'"; + throw Py::RuntimeError(str.str()); + } + return Py::None(); + } + else if (PyFloat_Check(index_or_value)) { + double rval = PyFloat_AsDouble(index_or_value); + if (!Interface_Static::SetRVal(name, rval)) { + std::stringstream str; + str << "Failed to set '" << name << "'"; + throw Py::RuntimeError(str.str()); + } + return Py::None(); + } + } + + throw Py::TypeError("First argument must be string and must be either string, int or float"); + } + Py::Object cast_to_shape(const Py::Tuple& args) + { + PyObject *object; + if (PyArg_ParseTuple(args.ptr(),"O!",&(Part::TopoShapePy::Type), &object)) { + TopoShape* ptr = static_cast(object)->getTopoShapePtr(); + TopoDS_Shape shape = ptr->_Shape; + if (!shape.IsNull()) { + TopAbs_ShapeEnum type = shape.ShapeType(); + switch (type) + { + case TopAbs_COMPOUND: + return Py::asObject(new TopoShapeCompoundPy(new TopoShape(shape))); + case TopAbs_COMPSOLID: + return Py::asObject(new TopoShapeCompSolidPy(new TopoShape(shape))); + case TopAbs_SOLID: + return Py::asObject(new TopoShapeSolidPy(new TopoShape(shape))); + case TopAbs_SHELL: + return Py::asObject(new TopoShapeShellPy(new TopoShape(shape))); + case TopAbs_FACE: + return Py::asObject(new TopoShapeFacePy(new TopoShape(shape))); + case TopAbs_WIRE: + return Py::asObject(new TopoShapeWirePy(new TopoShape(shape))); + case TopAbs_EDGE: + return Py::asObject(new TopoShapeEdgePy(new TopoShape(shape))); + case TopAbs_VERTEX: + return Py::asObject(new TopoShapeVertexPy(new TopoShape(shape))); + case TopAbs_SHAPE: + return Py::asObject(new TopoShapePy(new TopoShape(shape))); + default: + break; + } + } + else { + throw Py::Exception(PartExceptionOCCError, "empty shape"); + } + } + + throw Py::Exception(); + } + Py::Object getSortedClusters(const Py::Tuple& args) + { + PyObject *obj; + if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) { + throw Py::Exception(PartExceptionOCCError, "list of edges expected"); + } + Py::Sequence list(obj); std::vector edges; for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { @@ -1585,13 +1629,11 @@ static PyObject * getSortedClusters(PyObject *self, PyObject *args) if (sh.ShapeType() == TopAbs_EDGE) edges.push_back(TopoDS::Edge(sh)); else { - PyErr_SetString(PyExc_TypeError, "shape is not an edge"); - return 0; + throw Py::TypeError("shape is not an edge"); } } else { - PyErr_SetString(PyExc_TypeError, "item is not a shape"); - return 0; + throw Py::TypeError("item is not a shape"); } } @@ -1607,22 +1649,15 @@ static PyObject * getSortedClusters(PyObject *self, PyObject *args) root_list.append(add_list); } - return Py::new_reference_to(root_list); + return root_list; } - PY_CATCH_OCC; -} + Py::Object sortEdges(const Py::Tuple& args) + { + PyObject *obj; + if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) { + throw Py::TypeError("list of edges expected"); + } - -static PyObject * sortEdges(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_ParseTuple(args, "O", &obj)) { - PyErr_SetString(PartExceptionOCCError, "list of edges expected"); - return 0; - } - - - PY_TRY { Py::Sequence list(obj); std::vector edges; for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { @@ -1632,200 +1667,62 @@ static PyObject * sortEdges(PyObject *self, PyObject *args) if (sh.ShapeType() == TopAbs_EDGE) edges.push_back(TopoDS::Edge(sh)); else { - PyErr_SetString(PyExc_TypeError, "shape is not an edge"); - return 0; + throw Py::TypeError("shape is not an edge"); } } else { - PyErr_SetString(PyExc_TypeError, "item is not a shape"); - return 0; + throw Py::TypeError("item is not a shape"); } } std::list sorted = sort_Edges(Precision::Confusion(), edges); - Py::List sorted_list; for (std::list::iterator it = sorted.begin(); it != sorted.end(); ++it) { sorted_list.append(Py::Object(new TopoShapeEdgePy(new TopoShape(*it)),true)); } - return Py::new_reference_to(sorted_list); + return sorted_list; } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); - return 0; - } - PY_CATCH; -} + Py::Object toPythonOCC(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O!", &(TopoShapePy::Type), &pcObj)) + throw Py::Exception(); -static PyObject * cast_to_shape(PyObject *self, PyObject *args) -{ - PyObject *object; - if (PyArg_ParseTuple(args,"O!",&(Part::TopoShapePy::Type), &object)) { - TopoShape* ptr = static_cast(object)->getTopoShapePtr(); - TopoDS_Shape shape = ptr->_Shape; - if (!shape.IsNull()) { - TopAbs_ShapeEnum type = shape.ShapeType(); - switch (type) - { - case TopAbs_COMPOUND: - return new TopoShapeCompoundPy(new TopoShape(shape)); - case TopAbs_COMPSOLID: - return new TopoShapeCompSolidPy(new TopoShape(shape)); - case TopAbs_SOLID: - return new TopoShapeSolidPy(new TopoShape(shape)); - case TopAbs_SHELL: - return new TopoShapeShellPy(new TopoShape(shape)); - case TopAbs_FACE: - return new TopoShapeFacePy(new TopoShape(shape)); - case TopAbs_WIRE: - return new TopoShapeWirePy(new TopoShape(shape)); - case TopAbs_EDGE: - return new TopoShapeEdgePy(new TopoShape(shape)); - case TopAbs_VERTEX: - return new TopoShapeVertexPy(new TopoShape(shape)); - case TopAbs_SHAPE: - return new TopoShapePy(new TopoShape(shape)); - default: - break; - } + try { + TopoDS_Shape* shape = new TopoDS_Shape(); + (*shape) = static_cast(pcObj)->getTopoShapePtr()->_Shape; + PyObject* proxy = 0; + proxy = Base::Interpreter().createSWIGPointerObj("OCC.TopoDS", "TopoDS_Shape *", (void*)shape, 1); + return Py::asObject(proxy); } - else { - PyErr_SetString(PartExceptionOCCError, "empty shape"); + catch (const Base::Exception& e) { + throw Py::Exception(PartExceptionOCCError, e.what()); } } + Py::Object fromPythonOCC(const Py::Tuple& args) + { + PyObject *proxy; + if (!PyArg_ParseTuple(args.ptr(), "O", &proxy)) + throw Py::Exception(); - return 0; -} - -/* registration table */ -struct PyMethodDef Part_methods[] = { - {"open" ,open ,METH_VARARGS, - "open(string) -- Create a new document and load the file into the document."}, - - {"insert" ,insert ,METH_VARARGS, - "insert(string,string) -- Insert the file into the given document."}, - - {"export" ,exporter ,METH_VARARGS, - "export(list,string) -- Export a list of objects into a single file."}, - - {"read" ,read ,METH_VARARGS, - "read(string) -- Load the file and return the shape."}, - - {"show" ,show ,METH_VARARGS, - "show(shape) -- Add the shape to the active document or create one if no document exists."}, - - {"makeCompound" ,makeCompound ,METH_VARARGS, - "makeCompound(list) -- Create a compound out of a list of shapes."}, - - {"makeShell" ,makeShell ,METH_VARARGS, - "makeShell(list) -- Create a shell out of a list of faces."}, - - {"makeFilledFace" ,makeFilledFace ,METH_VARARGS, - "makeFilledFace(list) -- Create a face out of a list of edges."}, - - {"makeSolid" ,makeSolid ,METH_VARARGS, - "makeSolid(shape) -- Create a solid out of the shells inside a shape."}, - - {"makePlane" ,makePlane ,METH_VARARGS, - "makePlane(length,width,[pnt,dirZ,dirX]) -- Make a plane\n" - "By default pnt=Vector(0,0,0) and dirZ=Vector(0,0,1), dirX is ignored in this case"}, - - {"makeBox" ,makeBox ,METH_VARARGS, - "makeBox(length,width,height,[pnt,dir]) -- Make a box located\n" - "in pnt with the dimensions (length,width,height)\n" - "By default pnt=Vector(0,0,0) and dir=Vector(0,0,1)"}, - - {"makeWedge" ,makeWedge ,METH_VARARGS, - "makeWedge(xmin, ymin, zmin, z2min, x2min,\n" - "xmax, ymax, zmax, z2max, x2max,[pnt,dir])\n" - " -- Make a wedge located in pnt\n" - "By default pnt=Vector(0,0,0) and dir=Vector(0,0,1)"}, - - {"makeLine" ,makeLine ,METH_VARARGS, - "makeLine((x1,y1,z1),(x2,y2,z2)) -- Make a line of two points"}, - - {"makePolygon" ,makePolygon ,METH_VARARGS, - "makePolygon(list) -- Make a polygon of a list of points"}, - - {"makeCircle" ,makeCircle,METH_VARARGS, - "makeCircle(radius,[pnt,dir,angle1,angle2]) -- Make a circle with a given radius\n" - "By default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0 and angle2=360"}, - - {"makeSphere" ,makeSphere,METH_VARARGS, - "makeSphere(radius,[pnt, dir, angle1,angle2,angle3]) -- Make a sphere with a given radius\n" - "By default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0, angle2=90 and angle3=360"}, - - {"makeCylinder" ,makeCylinder,METH_VARARGS, - "makeCylinder(radius,height,[pnt,dir,angle]) -- Make a cylinder with a given radius and height\n" - "By default pnt=Vector(0,0,0),dir=Vector(0,0,1) and angle=360"}, - - {"makeCone" ,makeCone,METH_VARARGS, - "makeCone(radius1,radius2,height,[pnt,dir,angle]) -- Make a cone with given radii and height\n" - "By default pnt=Vector(0,0,0), dir=Vector(0,0,1) and angle=360"}, - - {"makeTorus" ,makeTorus,METH_VARARGS, - "makeTorus(radius1,radius2,[pnt,dir,angle1,angle2,angle]) -- Make a torus with a given radii and angles\n" - "By default pnt=Vector(0,0,0),dir=Vector(0,0,1),angle1=0,angle1=360 and angle=360"}, - - {"makeHelix" ,makeHelix,METH_VARARGS, - "makeHelix(pitch,height,radius,[angle]) -- Make a helix with a given pitch, height and radius\n" - "By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n" - "(the apex given in degree) a conical surface is used instead"}, - - {"makeLongHelix" ,makeLongHelix,METH_VARARGS, - "makeLongHelix(pitch,height,radius,[angle],[hand]) -- Make a (multi-edge) helix with a given pitch, height and radius\n" - "By default a cylindrical surface is used to create the helix. If the fourth parameter is set\n" - "(the apex given in degree) a conical surface is used instead."}, - - {"makeThread" ,makeThread,METH_VARARGS, - "makeThread(pitch,depth,height,radius) -- Make a thread with a given pitch, depth, height and radius"}, - - {"makeRevolution" ,makeRevolution,METH_VARARGS, - "makeRevolution(Curve,[vmin,vmax,angle,pnt,dir,shapetype]) -- Make a revolved shape\n" - "by rotating the curve or a portion of it around an axis given by (pnt,dir).\n" - "By default vmin/vmax=bounds of the curve,angle=360,pnt=Vector(0,0,0) and\n" - "dir=Vector(0,0,1) and shapetype=Part.Solid"}, - - {"makeRuledSurface" ,makeRuledSurface,METH_VARARGS, - "makeRuledSurface(Edge|Wire,Edge|Wire) -- Make a ruled surface\n" - "Create a ruled surface out of two edges or wires. If wires are used then" - "these must have the same number of edges."}, - - {"makeTube" ,makeTube,METH_VARARGS, - "makeTube(edge,radius,[continuity,max degree,max segments]) -- Create a tube.\n" - "continuity is a string which must be 'C0','C1','C2','C3','CN','G1' or 'G1',"}, - - {"makeSweepSurface" ,makeSweepSurface,METH_VARARGS, - "makeSweepSurface(edge(path),edge(profile),[float]) -- Create a profile along a path."}, - - {"makeLoft" ,makeLoft,METH_VARARGS, - "makeLoft(list of wires,[solid=False,ruled=False,closed=False]) -- Create a loft shape."}, - - {"makeWireString" ,makeWireString ,METH_VARARGS, - "makeWireString(string,fontdir,fontfile,height,[track]) -- Make list of wires in the form of a string's characters."}, - - {"exportUnits" ,exportUnits ,METH_VARARGS, - "exportUnits([string=MM|M|IN]) -- Set units for exporting STEP/IGES files and returns the units."}, - - {"setStaticValue" ,setStaticValue ,METH_VARARGS, - "setStaticValue(string,string|int|float) -- Set a name to a value The value can be a string, int or float."}, - - {"cast_to_shape" ,cast_to_shape,METH_VARARGS, - "cast_to_shape(shape) -- Cast to the actual shape type"}, - - {"getSortedClusters" ,getSortedClusters,METH_VARARGS, - "getSortedClusters(list of edges) -- Helper method to sort and cluster a variety of edges"}, - - {"__sortEdges__" ,sortEdges,METH_VARARGS, - "__sortEdges__(list of edges) -- Helper method to sort an unsorted list of edges so that afterwards\n" - "two adjacent edges share a common vertex"}, - - {"__toPythonOCC__" ,toPythonOCC,METH_VARARGS, - "__toPythonOCC__(shape) -- Helper method to convert an internal shape to pythonocc shape"}, - - {"__fromPythonOCC__" ,fromPythonOCC,METH_VARARGS, - "__fromPythonOCC__(occ) -- Helper method to convert a pythonocc shape to an internal shape"}, - {NULL, NULL} /* end of table marker */ + void* ptr; + try { + TopoShape* shape = new TopoShape(); + Base::Interpreter().convertSWIGPointerObj("OCC.TopoDS","TopoDS_Shape *", proxy, &ptr, 0); + TopoDS_Shape* s = reinterpret_cast(ptr); + shape->_Shape = (*s); + return Py::asObject(new TopoShapePy(shape)); + } + catch (const Base::Exception& e) { + throw Py::Exception(PartExceptionOCCError, e.what()); + } + } }; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace Part diff --git a/src/Mod/Part/Gui/AppPartGui.cpp b/src/Mod/Part/Gui/AppPartGui.cpp index 66ee44192..ec119b937 100644 --- a/src/Mod/Part/Gui/AppPartGui.cpp +++ b/src/Mod/Part/Gui/AppPartGui.cpp @@ -16,6 +16,9 @@ # include #endif +#include +#include + #include #include @@ -77,13 +80,28 @@ void loadPartResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -static struct PyMethodDef PartGui_methods[] = { - {NULL, NULL} /* end of table marker */ +namespace PartGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("PartGui") + { + initialize("This module is the PartGui module."); // register with Python + } + + virtual ~Module() {} + +private: }; -extern "C" { -void PartGuiExport initPartGui() +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace PartGui + +PyMODINIT_FUNC initPartGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -99,7 +117,7 @@ void PartGuiExport initPartGui() return; } - (void) Py_InitModule("PartGui", PartGui_methods); /* mod name, table ptr */ + (void)PartGui::initModule(); Base::Console().Log("Loading GUI of Part module... done\n"); PartGui::SoBrepFaceSet ::initClass(); @@ -176,4 +194,3 @@ void PartGuiExport initPartGui() rclBmpFactory.addXPM("PartFeature",(const char**) PartFeature_xpm); rclBmpFactory.addXPM("PartFeatureImport",(const char**) PartFeatureImport_xpm); } -} // extern "C"