diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 8c056e30b7..4215d6185c 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -220,11 +220,13 @@ Application::Application(ParameterManager * /*pcSysParamMngr*/, PyObject* pBaseModule = Py_InitModule3("__FreeCADBase__", NULL, "The Base module contains the classes for the geometric basics\n" "like vector, matrix, bounding box, placement, rotation, axis, ..."); - Base::BaseExceptionFreeCADError = PyErr_NewException( - "Base.FreeCADError", PyExc_RuntimeError, NULL); + + // Python exceptions + Base::BaseExceptionFreeCADError = PyErr_NewException("Base.FreeCADError", PyExc_RuntimeError, NULL); Py_INCREF(Base::BaseExceptionFreeCADError); - PyModule_AddObject(pBaseModule, "FreeCADError", - Base::BaseExceptionFreeCADError); + PyModule_AddObject(pBaseModule, "FreeCADError", Base::BaseExceptionFreeCADError); + + // Python types Base::Interpreter().addType(&Base::VectorPy ::Type,pBaseModule,"Vector"); Base::Interpreter().addType(&Base::MatrixPy ::Type,pBaseModule,"Matrix"); Base::Interpreter().addType(&Base::BoundBoxPy ::Type,pBaseModule,"BoundBox"); diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 4e68baf87c..b121125ed7 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -287,7 +287,7 @@ void PropertyFileIncluded::setPyObject(PyObject *value) fileStr = PyString_AsString(FileName); } else { - std::string error = std::string("First item in tuple must be a file or string"); + std::string error = std::string("First item in tuple must be a file or string, not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } @@ -302,7 +302,7 @@ void PropertyFileIncluded::setPyObject(PyObject *value) nameStr = PyString_AsString(FileName); } else { - std::string error = std::string("Second item in tuple must be a string"); + std::string error = std::string("Second item in tuple must be a string, not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } @@ -311,7 +311,7 @@ void PropertyFileIncluded::setPyObject(PyObject *value) return; } else { - std::string error = std::string("Type must be string or file"); + std::string error = std::string("Type must be string or file, not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } diff --git a/src/Gui/GuiApplicationNativeEventAware.cpp b/src/Gui/GuiApplicationNativeEventAware.cpp index 4f782d3613..829572dc1c 100644 --- a/src/Gui/GuiApplicationNativeEventAware.cpp +++ b/src/Gui/GuiApplicationNativeEventAware.cpp @@ -73,18 +73,14 @@ Gui::GUIApplicationNativeEventAware::~GUIApplicationNativeEventAware() #endif //mac #ifdef Q_WS_MACX - /* make sure the framework is installed */ - if (InstallConnexionHandlers == NULL) - { - Base::Console().Log("3Dconnexion framework not found!\n"); - return; - } - /* close the connection with the 3dx driver */ - //std::cerr << "tdxClientID: " << tdxClientID << std::endl; - if (tdxClientID) - UnregisterConnexionClient(tdxClientID); - CleanupConnexionHandlers(); - Base::Console().Log("Disconnected from 3DConnexion driver\n"); + // if 3Dconnexion library was loaded at runtime + if (InstallConnexionHandlers) { + // Close our connection with the 3dx driver + if (tdxClientID) + UnregisterConnexionClient(tdxClientID); + CleanupConnexionHandlers(); + Base::Console().Log("Disconnected from 3Dconnexion driver\n"); + } #endif #endif } @@ -123,33 +119,33 @@ void Gui::GUIApplicationNativeEventAware::initSpaceball(QMainWindow *window) OSStatus err; /* make sure the framework is installed */ if (InstallConnexionHandlers == NULL) - { + { Base::Console().Log("3Dconnexion framework not found!\n"); return; - } + } /* install 3dx message handler in order to receive driver events */ err = InstallConnexionHandlers(tdx_drv_handler, 0L, 0L); assert(err == 0); if (err) - { + { Base::Console().Log("Error installing 3Dconnexion handler\n"); return; - } + } /* register our app with the driver */ - //Pascal string Application name required to register driver for application + // Pascal string Application name required to register driver for application UInt8 tdxAppName[] = {7,'F','r','e','e','C','A','D'}; - //32bit appID to register driver for application + // 32bit appID to register driver for application UInt32 tdxAppID = 'FCAd'; - //std::cerr << "tdxClientID: " << tdxClientID << std::endl; - tdxClientID = RegisterConnexionClient(tdxAppID, tdxAppName, kConnexionClientModeTakeOver, kConnexionMaskAll); - //std::cerr << "tdxClientID: " << tdxClientID << std::endl; + tdxClientID = RegisterConnexionClient( tdxAppID, tdxAppName, + kConnexionClientModeTakeOver, + kConnexionMaskAll ); if (tdxClientID == 0) - { + { Base::Console().Log("Couldn't connect to 3Dconnexion driver\n"); return; - } + } - Base::Console().Log("3Dconnexion device initialized. Client ID: %d\n", tdxClientID); + Base::Console().Log("3Dconnexion driver initialized. Client ID: %d\n", tdxClientID); spaceballPresent = true; #endif #endif // _USE_3DCONNEXION_SDK diff --git a/src/Gui/GuiApplicationNativeEventAware.h b/src/Gui/GuiApplicationNativeEventAware.h index 243269f333..b52cb0576b 100644 --- a/src/Gui/GuiApplicationNativeEventAware.h +++ b/src/Gui/GuiApplicationNativeEventAware.h @@ -46,9 +46,14 @@ class QMainWindow; #ifdef Q_WS_MACX #include #include -extern OSErr InstallConnexionHandlers(ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler) - __attribute__((weak_import)); -extern UInt16 RegisterConnexionClient(UInt32 signature, UInt8 *name, UInt16 mode, UInt32 mask) __attribute__((weak_import)); +// Note that InstallConnexionHandlers will be replaced with +// SetConnexionHandlers "in the future". +extern OSErr InstallConnexionHandlers(ConnexionMessageHandlerProc messageHandler, + ConnexionAddedHandlerProc addedHandler, + ConnexionRemovedHandlerProc removedHandler) + __attribute__((weak_import)); +extern UInt16 RegisterConnexionClient(UInt32 signature, UInt8 *name, UInt16 mode, + UInt32 mask) __attribute__((weak_import)); extern void UnregisterConnexionClient(UInt16 clientID) __attribute__((weak_import)); extern void CleanupConnexionHandlers(void) __attribute__((weak_import)); #endif // Q_WS_MACX @@ -129,12 +134,14 @@ namespace Gui #endif // Q_WS_WIN #ifdef Q_WS_MACX private: - static UInt16 tdxClientID; /* ID assigned by the driver */ - static uint32_t lastButtons; + static UInt16 tdxClientID; /* ID assigned by the driver */ + static uint32_t lastButtons; public: - static void tdx_drv_handler(io_connect_t connection, natural_t messageType, void *messageArgument); - void Move3d(); - void Button3d(bool buttonDown, int buttonNumber); + static void tdx_drv_handler( io_connect_t connection, + natural_t messageType, + void *messageArgument ); + void Move3d(); + void Button3d(bool buttonDown, int buttonNumber); #endif// Q_WS_MACX #endif // _USE_3DCONNEXION_SDK diff --git a/src/Mod/Complete/App/AppComplete.cpp b/src/Mod/Complete/App/AppComplete.cpp index 1c1b953200..5c202fc90f 100644 --- a/src/Mod/Complete/App/AppComplete.cpp +++ b/src/Mod/Complete/App/AppComplete.cpp @@ -26,20 +26,38 @@ # include #endif +#include +#include + #include #include #include "CompleteConfiguration.h" -extern struct PyMethodDef Complete_methods[]; +namespace Complete { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("Complete") + { + initialize("This module is the Complete module."); // register with Python + } -PyDoc_STRVAR(module_Complete_doc, -"This module is the Complete module."); + virtual ~Module() {} + +private: +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace Complete /* Python entry */ -extern "C" { -void AppCompleteExport initComplete() +PyMODINIT_FUNC initComplete() { // load dependent module try { @@ -70,8 +88,6 @@ void AppCompleteExport initComplete() PyErr_SetString(PyExc_ImportError, e.what()); return; } - Py_InitModule3("Complete", Complete_methods, module_Complete_doc); /* mod name, table ptr */ + (void)Complete::initModule(); Base::Console().Log("Loading Complete module... done\n"); } - -} // extern "C" diff --git a/src/Mod/Complete/App/AppCompletePy.cpp b/src/Mod/Complete/App/AppCompletePy.cpp deleted file mode 100644 index eb7ce96a11..0000000000 --- a/src/Mod/Complete/App/AppCompletePy.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -#endif - - -/* registration table */ -struct PyMethodDef Complete_methods[] = { - {NULL, NULL} /* end of table marker */ -}; diff --git a/src/Mod/Complete/App/CMakeLists.txt b/src/Mod/Complete/App/CMakeLists.txt index abeac43c77..324315831f 100644 --- a/src/Mod/Complete/App/CMakeLists.txt +++ b/src/Mod/Complete/App/CMakeLists.txt @@ -15,7 +15,6 @@ set(Complete_LIBS SET(Complete_SRCS AppComplete.cpp - AppCompletePy.cpp PreCompiled.cpp PreCompiled.h CompleteConfiguration.h diff --git a/src/Mod/Complete/Gui/AppCompleteGui.cpp b/src/Mod/Complete/Gui/AppCompleteGui.cpp index 4bd8690378..6709afeaa1 100644 --- a/src/Mod/Complete/Gui/AppCompleteGui.cpp +++ b/src/Mod/Complete/Gui/AppCompleteGui.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -48,13 +51,30 @@ void loadCompleteResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef CompleteGui_Import_methods[]; +namespace CompleteGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("CompleteGui") + { + initialize("This module is the CompleteGui module."); // register with Python + } + + virtual ~Module() {} + +private: +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace CompleteGui /* Python entry */ -extern "C" { -void CompleteGuiExport initCompleteGui() +PyMODINIT_FUNC initCompleteGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -116,7 +136,7 @@ void CompleteGuiExport initCompleteGui() } # endif - (void) Py_InitModule("CompleteGui", CompleteGui_Import_methods); /* mod name, table ptr */ + (void) CompleteGui::initModule(); Base::Console().Log("Loading GUI of Complete module... done\n"); // instantiating the commands @@ -126,5 +146,3 @@ void CompleteGuiExport initCompleteGui() // add resources and reloads the translators loadCompleteResource(); } - -} // extern "C" { diff --git a/src/Mod/Complete/Gui/AppCompleteGuiPy.cpp b/src/Mod/Complete/Gui/AppCompleteGuiPy.cpp deleted file mode 100644 index 478c49af34..0000000000 --- a/src/Mod/Complete/Gui/AppCompleteGuiPy.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2008 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -#endif - - -/* registration table */ -struct PyMethodDef CompleteGui_Import_methods[] = { - {NULL, NULL} /* end of table marker */ -}; diff --git a/src/Mod/Complete/Gui/CMakeLists.txt b/src/Mod/Complete/Gui/CMakeLists.txt index 091cfb2370..2e8ebfe921 100644 --- a/src/Mod/Complete/Gui/CMakeLists.txt +++ b/src/Mod/Complete/Gui/CMakeLists.txt @@ -18,7 +18,6 @@ qt4_add_resources(Complete_QRC_SRCS Resources/Complete.qrc) SET(CompleteGui_SRCS ${Complete_QRC_SRCS} AppCompleteGui.cpp - AppCompleteGuiPy.cpp Command.cpp PreCompiled.cpp PreCompiled.h diff --git a/src/Mod/Draft/App/AppDraftUtils.cpp b/src/Mod/Draft/App/AppDraftUtils.cpp index c2ef092bca..5464282ade 100644 --- a/src/Mod/Draft/App/AppDraftUtils.cpp +++ b/src/Mod/Draft/App/AppDraftUtils.cpp @@ -29,25 +29,21 @@ #include #include -extern struct PyMethodDef DraftUtils_methods[]; - -PyDoc_STRVAR(module_DraftUtils_doc, "The DraftUtils module contains utility functions for the Draft module."); +namespace DraftUtils { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { - - void DraftUtilsExport initDraftUtils() - { - // load dependent module - try { - Base::Interpreter().loadModule("Part"); - } - catch(const Base::Exception& e) { - PyErr_SetString(PyExc_ImportError, e.what()); - return; - } - Py_InitModule3("DraftUtils", DraftUtils_methods, module_DraftUtils_doc); /* mod name, table ptr */ - Base::Console().Log("Loading DraftUtils module... done\n"); +PyMODINIT_FUNC initDraftUtils() +{ + // load dependent module + try { + Base::Interpreter().loadModule("Part"); } - -} // extern "C" + catch(const Base::Exception& e) { + PyErr_SetString(PyExc_ImportError, e.what()); + return; + } + (void)DraftUtils::initModule(); + Base::Console().Log("Loading DraftUtils module... done\n"); +} diff --git a/src/Mod/Draft/App/AppDraftUtilsPy.cpp b/src/Mod/Draft/App/AppDraftUtilsPy.cpp index 33d08a3d7f..c334c444c3 100644 --- a/src/Mod/Draft/App/AppDraftUtilsPy.cpp +++ b/src/Mod/Draft/App/AppDraftUtilsPy.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -36,46 +39,61 @@ #include "DraftDxf.h" -using namespace DraftUtils; - -static PyObject * readDXF (PyObject *self, PyObject *args) +namespace DraftUtils { +class Module : public Py::ExtensionModule { - char* Name; - const char* DocName=0; - bool IgnoreErrors=true; - if (!PyArg_ParseTuple(args, "et|sb","utf-8",&Name,&DocName,&IgnoreErrors)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("DraftUtils") + { + add_varargs_method("readDXF",&Module::readDXF, + "readDXF(filename,[document,ignore_errors]): Imports a DXF file into the given document. ignore_errors is True by default." + ); + initialize("The DraftUtils module contains utility functions for the Draft module."); // register with Python + } - Base::FileInfo file(EncodedName.c_str()); - if (!file.exists()) - Py_Error(Base::BaseExceptionFreeCADError, "File doesn't exist"); - App::Document *pcDoc; - if (DocName) - pcDoc = App::GetApplication().getDocument(DocName); - else - pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(DocName); + virtual ~Module() {} - PY_TRY { - // read the DXF file - DraftDxfRead dxf_file(EncodedName,pcDoc); - dxf_file.DoRead(IgnoreErrors); - pcDoc->recompute(); - } PY_CATCH; - Py_Return; +private: + Py::Object readDXF(const Py::Tuple& args) + { + char* Name; + const char* DocName=0; + bool IgnoreErrors=true; + if (!PyArg_ParseTuple(args.ptr(), "et|sb","utf-8",&Name,&DocName,&IgnoreErrors)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + Base::FileInfo file(EncodedName.c_str()); + if (!file.exists()) + throw Py::RuntimeError("File doesn't exist"); + + App::Document *pcDoc; + if (DocName) + pcDoc = App::GetApplication().getDocument(DocName); + else + pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(DocName); + + try { + // read the DXF file + DraftDxfRead dxf_file(EncodedName,pcDoc); + dxf_file.DoRead(IgnoreErrors); + pcDoc->recompute(); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } - - - -/* registration table */ -struct PyMethodDef DraftUtils_methods[] = { - - {"readDXF" ,readDXF ,METH_VARARGS, - "readDXF(filename,[document,ignore_errors]): Imports a DXF file into the given document. ignore_errors is True by default."}, - - {NULL, NULL} /* end of table marker */ -}; +} // namespace DraftUtils diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index 5f1caded65..3e9edf6ee4 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -474,43 +474,48 @@ def pocket2d(shape,offset): if not o.Wires: return [] offsetWires = o.Wires - print("base offset wires:",offsetWires) + #print("base offset wires:",offsetWires) if not innerWires: return offsetWires for innerWire in innerWires: i = innerWire.makeOffset(offset) + if len(innerWire.Edges) == 1: + e = innerWire.Edges[0] + if isinstance(e.Curve,Part.Circle): + e = Part.makeCircle(e.Curve.Radius+offset,e.Curve.Center,e.Curve.Axis) + i = Part.Wire(e) if i.Wires: - print("offsetting island ",innerWire," : ",i.Wires) + #print("offsetting island ",innerWire," : ",i.Wires) for w in i.Wires: added = False - print("checking wire ",w) + #print("checking wire ",w) k = list(range(len(offsetWires))) for j in k: - print("checking against existing wire ",j) + #print("checking against existing wire ",j) ow = offsetWires[j] if ow: if wiresIntersect(w,ow): - print("intersect") + #print("intersect") f1 = Part.Face(ow) f2 = Part.Face(w) f3 = f1.cut(f2) - print("made new wires: ",f3.Wires) + #print("made new wires: ",f3.Wires) offsetWires[j] = f3.Wires[0] if len(f3.Wires) > 1: - print("adding more") + #print("adding more") offsetWires.extend(f3.Wires[1:]) added = True else: a = w.BoundBox b = ow.BoundBox if (a.XMin <= b.XMin) and (a.YMin <= b.YMin) and (a.ZMin <= b.ZMin) and (a.XMax >= b.XMax) and (a.YMax >= b.YMax) and (a.ZMax >= b.ZMax): - print("this wire is bigger than the outer wire") + #print("this wire is bigger than the outer wire") offsetWires[j] = None added = True - else: - print("doesn't intersect") + #else: + #print("doesn't intersect") if not added: - print("doesn't intersect with any other") + #print("doesn't intersect with any other") offsetWires.append(w) offsetWires = [o for o in offsetWires if o != None] return offsetWires @@ -2057,9 +2062,38 @@ def tessellateProjection(shape,seglen): except: print("Debug: error cleaning edge ",e) return Part.makeCompound(newedges) + + +def rebaseWire(wire,vidx): + + """rebaseWire(wire,vidx): returns a new wire which is a copy of the + current wire, but where the first vertex is the vertex indicated by the given + index vidx, starting from 1. 0 will return an exact copy of the wire.""" + + if vidx < 1: + return wire + if vidx > len(wire.Vertexes): + #print("Vertex index above maximum\n") + return wire + basepoint = wire.Vertexes[vidx-1].Point + #wire = Part.__sortEdges__(wire) + edges = [] + start = False + for i in range(len(wire.Edges)): + if wire.Edges[i].Vertexes[0].Point == basepoint: + start = True + edges.append(wire.Edges[i]) + elif start: + edges.append(wire.Edges[i]) + if len(edges) < len(wire.Edges): + f = len(wire.Edges) - len(edges) + edges.extend(wire.Edges[0:f]) + return Part.Wire(edges) + # circle functions ********************************************************* + def getBoundaryAngles(angle,alist): '''returns the 2 closest angles from the list that encompass the given angle''' diff --git a/src/Mod/Drawing/App/AppDrawing.cpp b/src/Mod/Drawing/App/AppDrawing.cpp index 9e0203a1cd..915064a3a9 100644 --- a/src/Mod/Drawing/App/AppDrawing.cpp +++ b/src/Mod/Drawing/App/AppDrawing.cpp @@ -27,15 +27,13 @@ #include "FeatureClip.h" #include "PageGroup.h" -extern struct PyMethodDef Drawing_methods[]; - -PyDoc_STRVAR(module_drawing_doc, -"This module is the drawing module."); +namespace Drawing { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void DrawingExport initDrawing() +PyMODINIT_FUNC initDrawing() { // load dependent module try { @@ -46,7 +44,7 @@ void DrawingExport initDrawing() PyErr_SetString(PyExc_ImportError, e.what()); return; } - Py_InitModule3("Drawing", Drawing_methods, module_drawing_doc); /* mod name, table ptr */ + (void)Drawing::initModule(); Base::Console().Log("Loading Drawing module... done\n"); @@ -66,5 +64,3 @@ void DrawingExport initDrawing() Drawing::FeatureClip ::init(); Drawing::FeatureViewSpreadsheet ::init(); } - -} // extern "C" diff --git a/src/Mod/Drawing/App/AppDrawingPy.cpp b/src/Mod/Drawing/App/AppDrawingPy.cpp index 6341d28612..d02e90ba68 100644 --- a/src/Mod/Drawing/App/AppDrawingPy.cpp +++ b/src/Mod/Drawing/App/AppDrawingPy.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include "ProjectionAlgos.h" #include @@ -34,21 +37,84 @@ #include -using namespace Drawing; -using namespace Part; -using namespace std; +using Part::TopoShapePy; +using Part::TopoShape; -static PyObject * -project(PyObject *self, PyObject *args) +namespace Drawing { +class Module : public Py::ExtensionModule { - PyObject *pcObjShape; - PyObject *pcObjDir=0; +public: + Module() : Py::ExtensionModule("Drawing") + { + add_varargs_method("project",&Module::project, + "[visiblyG0,visiblyG1,hiddenG0,hiddenG1] = project(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the visible/invisible parts of it." + ); + add_varargs_method("projectEx",&Module::projectEx, + "[V,V1,VN,VO,VI,H,H1,HN,HO,HI] = projectEx(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the all parts of it." + ); + add_varargs_method("projectToSVG",&Module::projectToSVG, + "string = projectToSVG(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the SVG representation as string." + ); + add_varargs_method("projectToDXF",&Module::projectToDXF, + "string = projectToDXF(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the DXF representation as string." + ); + add_varargs_method("removeSvgTags",&Module::removeSvgTags, + "string = removeSvgTags(string) -- Removes the opening and closing svg tags\n" + "and other metatags from a svg code, making it embeddable" + ); + initialize("This module is the Drawing module."); // register with Python + } - if (!PyArg_ParseTuple(args, "O!|O!", &(TopoShapePy::Type), &pcObjShape,&(Base::VectorPy::Type), &pcObjDir)) // convert args: Python->C - return NULL; // NULL triggers exception + virtual ~Module() {} - PY_TRY { - TopoShapePy* pShape = static_cast(pcObjShape); +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 project(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + + if (!PyArg_ParseTuple(args.ptr(), "O!|O!", + &(Part::TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir)) + throw Py::Exception(); + + Part::TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) Vector = *static_cast(pcObjDir)->getVectorPtr(); @@ -56,27 +122,23 @@ project(PyObject *self, PyObject *args) ProjectionAlgos Alg(pShape->getTopoShapePtr()->_Shape,Vector); Py::List list; - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V)) , true)); - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V1)), true)); - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H)) , true)); - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H1)), true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V)) , true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V1)), true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H)) , true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H1)), true)); - return Py::new_reference_to(list); + return list; + } + Py::Object projectEx(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; - } PY_CATCH_OCC; + if (!PyArg_ParseTuple(args.ptr(), "O!|O!", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir)) + throw Py::Exception(); -} - -static PyObject * -projectEx(PyObject *self, PyObject *args) -{ - PyObject *pcObjShape; - PyObject *pcObjDir=0; - - if (!PyArg_ParseTuple(args, "O!|O!", &(TopoShapePy::Type), &pcObjShape,&(Base::VectorPy::Type), &pcObjDir)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) @@ -96,25 +158,21 @@ projectEx(PyObject *self, PyObject *args) list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HO)), true)); list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HI)), true)); - return Py::new_reference_to(list); + return list; + } + Py::Object projectToSVG(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + const char *type=0; + float scale=1.0f; + float tol=0.1f; - } PY_CATCH_OCC; -} + if (!PyArg_ParseTuple(args.ptr(), "O!|O!sff", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) + throw Py::Exception(); -static PyObject * -projectToSVG(PyObject *self, PyObject *args) -{ - PyObject *pcObjShape; - PyObject *pcObjDir=0; - const char *type=0; - float scale=1.0f; - float tol=0.1f; - - if (!PyArg_ParseTuple(args, "O!|O!sff", &(TopoShapePy::Type), &pcObjShape, - &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) - return NULL; - - PY_TRY { TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) @@ -126,25 +184,21 @@ projectToSVG(PyObject *self, PyObject *args) hidden = true; Py::String result(Alg.getSVG(hidden?ProjectionAlgos::WithHidden:ProjectionAlgos::Plain, scale, tol)); - return Py::new_reference_to(result); + return result; + } + Py::Object projectToDXF(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + const char *type=0; + float scale=1.0f; + float tol=0.1f; - } PY_CATCH_OCC; -} + if (!PyArg_ParseTuple(args.ptr(), "O!|O!sff", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) + throw Py::Exception(); -static PyObject * -projectToDXF(PyObject *self, PyObject *args) -{ - PyObject *pcObjShape; - PyObject *pcObjDir=0; - const char *type=0; - float scale=1.0f; - float tol=0.1f; - - if (!PyArg_ParseTuple(args, "O!|O!sff", &(TopoShapePy::Type), &pcObjShape, - &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) - return NULL; - - PY_TRY { TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) @@ -156,23 +210,18 @@ projectToDXF(PyObject *self, PyObject *args) hidden = true; Py::String result(Alg.getDXF(hidden?ProjectionAlgos::WithHidden:ProjectionAlgos::Plain, scale, tol)); - return Py::new_reference_to(result); + return result; + } + Py::Object removeSvgTags(const Py::Tuple& args) + { + const char* svgcode; + if (!PyArg_ParseTuple(args.ptr(), "s",&svgcode)) + throw Py::Exception(); - } PY_CATCH_OCC; -} - -static PyObject * -removeSvgTags(PyObject *self, PyObject *args) -{ - const char* svgcode; - if (!PyArg_ParseTuple(args, "s",&svgcode)) - return NULL; - - PY_TRY { - string svg(svgcode); - string empty = ""; - string endline = "--endOfLine--"; - string linebreak = "\\n"; + std::string svg(svgcode); + std::string empty = ""; + std::string endline = "--endOfLine--"; + std::string linebreak = "\\n"; // removing linebreaks for regex to work boost::regex e1 ("\\n"); svg = boost::regex_replace(svg, e1, endline); @@ -195,23 +244,13 @@ removeSvgTags(PyObject *self, PyObject *args) boost::regex e7 ("--endOfLine--"); svg = boost::regex_replace(svg, e7, linebreak); Py::String result(svg); - return Py::new_reference_to(result); - } PY_CATCH_OCC; + return result; + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } - - -/* registration table */ -struct PyMethodDef Drawing_methods[] = { - {"project" ,project ,METH_VARARGS, - "[visiblyG0,visiblyG1,hiddenG0,hiddenG1] = project(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the visible/invisible parts of it."}, - {"projectEx" ,projectEx ,METH_VARARGS, - "[V,V1,VN,VO,VI,H,H1,HN,HO,HI] = projectEx(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the all parts of it."}, - {"projectToSVG" ,projectToSVG ,METH_VARARGS, - "string = projectToSVG(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the SVG representation as string."}, - {"projectToDXF" ,projectToDXF ,METH_VARARGS, - "string = projectToDXF(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the DXF representation as string."}, - {"removeSvgTags" ,removeSvgTags ,METH_VARARGS, - "string = removeSvgTags(string) -- Removes the opening and closing svg tags and other metatags from a svg code, making it embeddable"}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace Drawing diff --git a/src/Mod/Drawing/Gui/AppDrawingGui.cpp b/src/Mod/Drawing/Gui/AppDrawingGui.cpp index cf481d2c19..d45a891734 100644 --- a/src/Mod/Drawing/Gui/AppDrawingGui.cpp +++ b/src/Mod/Drawing/Gui/AppDrawingGui.cpp @@ -43,20 +43,20 @@ void loadDrawingResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef DrawingGui_Import_methods[]; +namespace DrawingGui { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void DrawingGuiExport initDrawingGui() +PyMODINIT_FUNC initDrawingGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); return; } - (void) Py_InitModule("DrawingGui", DrawingGui_Import_methods); /* mod name, table ptr */ + (void) DrawingGui::initModule(); Base::Console().Log("Loading GUI of Drawing module... done\n"); // instantiating the commands @@ -71,5 +71,3 @@ void DrawingGuiExport initDrawingGui() // add resources and reloads the translators loadDrawingResource(); } - -} // extern "C" { diff --git a/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp b/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp index 1445cd0abd..f4e052fb27 100644 --- a/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp +++ b/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp @@ -28,6 +28,9 @@ # include #endif +#include +#include + #include "DrawingView.h" #include #include @@ -43,20 +46,45 @@ #include #include -using namespace DrawingGui; - - -/* module functions */ -static PyObject * -open(PyObject *self, PyObject *args) +namespace DrawingGui { +class Module : public Py::ExtensionModule { - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("DrawingGui") + { + add_varargs_method("open",&Module::open + ); + add_varargs_method("insert",&Module::importer + ); + add_varargs_method("export",&Module::exporter + ); + initialize("This module is the DrawingGui module."); // register with Python + } + + 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 Base::Exception &e) { + throw Py::RuntimeError(e.what()); + } + catch (const std::exception &e) { + throw Py::RuntimeError(e.what()); + } + } + 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); - PY_TRY { Base::FileInfo file(EncodedName.c_str()); if (file.hasExtension("svg") || file.hasExtension("svgz")) { QString fileName = QString::fromUtf8(EncodedName.c_str()); @@ -70,26 +98,21 @@ open(PyObject *self, PyObject *args) Gui::getMainWindow()->addWindow(view); } else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "unknown filetype"); - return NULL; + throw Py::Exception(Base::BaseExceptionFreeCADError, "unknown filetype"); } - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object importer(const Py::Tuple& args) + { + char* Name; + const char* dummy; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&dummy)) + throw Py::Exception(); -/* module functions */ -static PyObject * -importer(PyObject *self, PyObject *args) -{ - char* Name; - const char* dummy; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&dummy)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { Base::FileInfo file(EncodedName.c_str()); if (file.hasExtension("svg") || file.hasExtension("svgz")) { QString fileName = QString::fromUtf8(EncodedName.c_str()); @@ -102,25 +125,21 @@ importer(PyObject *self, PyObject *args) view->resize( 400, 300 ); Gui::getMainWindow()->addWindow(view); } else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "unknown filetype"); - return NULL; + throw Py::Exception(Base::BaseExceptionFreeCADError, "unknown filetype"); } - } PY_CATCH; - Py_Return; -} + 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(); -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); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { Py::Sequence list(object); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { PyObject* item = (*it).ptr(); @@ -132,8 +151,7 @@ exporter(PyObject *self, PyObject *args) if (!str_out) { std::stringstream str; str << "Cannot open file '" << EncodedName << "' for writing"; - PyErr_SetString(PyExc_IOError, str.str().c_str()); - return NULL; + throw Py::Exception(PyExc_IOError, str.str().c_str()); } if (fi_out.hasExtension("svg")) { std::string fn = static_cast(obj)->PageResult.getValue(); @@ -142,8 +160,7 @@ exporter(PyObject *self, PyObject *args) if (!str_in) { std::stringstream str; str << "Cannot open file '" << fn << "' for reading"; - PyErr_SetString(PyExc_IOError, str.str().c_str()); - return NULL; + throw Py::Exception(PyExc_IOError, str.str().c_str()); } str_in >> str_out.rdbuf(); @@ -159,12 +176,10 @@ exporter(PyObject *self, PyObject *args) std::string viewName = view->Label.getValue(); App::DocumentObject* link = view->Source.getValue(); if (!link) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "No object linked"); - return 0; + throw Py::Exception(Base::BaseExceptionFreeCADError, "No object linked"); } if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { - PyErr_SetString(PyExc_TypeError, "Linked object is not a Part object"); - return 0; + throw Py::TypeError("Linked object is not a Part object"); } TopoDS_Shape shape = static_cast(link)->Shape.getShape()._Shape; if (!shape.IsNull()) { @@ -187,25 +202,22 @@ exporter(PyObject *self, PyObject *args) break; } else { - PyErr_SetString(PyExc_TypeError, "Export of page object as this file format is not supported by Drawing module"); - return 0; + throw Py::TypeError("Export of page object as this file format is not supported by Drawing module"); } } else { - PyErr_SetString(PyExc_TypeError, "Export of this object type is not supported by Drawing module"); - return 0; + throw Py::TypeError("Export of this object type is not supported by Drawing module"); } } } - } PY_CATCH; - Py_Return; + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef DrawingGui_Import_methods[] = { - {"open" ,open , METH_VARARGS}, /* method name, C func ptr, always-tuple */ - {"insert" ,importer, METH_VARARGS}, - {"export" ,exporter, METH_VARARGS}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace DrawingGui diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index 1a6fc95ddd..97f38e44df 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -54,14 +54,12 @@ #include "FemResultObject.h" #include "FemSolverObject.h" -extern struct PyMethodDef Fem_methods[]; - -PyDoc_STRVAR(module_Fem_doc, -"This module is the FEM module."); +namespace Fem { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void AppFemExport initFem() +PyMODINIT_FUNC initFem() { // load dependend module try { @@ -72,7 +70,7 @@ void AppFemExport initFem() PyErr_SetString(PyExc_ImportError, e.what()); return; } - PyObject* femModule = Py_InitModule3("Fem", Fem_methods, module_Fem_doc); /* mod name, table ptr */ + PyObject* femModule = Fem::initModule(); Base::Console().Log("Loading Fem module... done\n"); Fem::StdMeshers_Arithmetic1DPy ::init_type(femModule); @@ -146,5 +144,3 @@ void AppFemExport initFem() Fem::FemSolverObject ::init(); Fem::FemSolverObjectPython ::init(); } - -} // extern "C" diff --git a/src/Mod/Fem/App/AppFemPy.cpp b/src/Mod/Fem/App/AppFemPy.cpp index 0a4a8bbeaa..22c3832980 100644 --- a/src/Mod/Fem/App/AppFemPy.cpp +++ b/src/Mod/Fem/App/AppFemPy.cpp @@ -27,6 +27,9 @@ # include #endif +#include +#include + #include #include #include @@ -66,44 +69,66 @@ #include #include -#include "Base/Vector3D.h" +#include +#include -using namespace Fem; - - -/* module functions */ -static PyObject * read(PyObject *self, PyObject *args) +namespace Fem { +class Module : public Py::ExtensionModule { - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("Fem") + { + add_varargs_method("open",&Module::open, + "open(string) -- Create a new document and a Mesh::Import feature to load the file into the document." + ); + add_varargs_method("insert",&Module::insert, + "insert(string|mesh,[string]) -- Load or insert a mesh into the given or active 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 a mesh from a file and returns a Mesh object." + ); + add_varargs_method("show",&Module::show, + "show(shape) -- Add the shape to the active document or create one if no document exists." + ); + initialize("This module is the Fem module."); // register with Python + } - PY_TRY { - std::auto_ptr mesh(new FemMesh); + virtual ~Module() {} + +private: + virtual Py::Object invoke_method_varargs(void *method_def, const Py::Tuple &args) + { try { - mesh->read(EncodedName.c_str()); - return new FemMeshPy(mesh.release()); + return Py::ExtensionModule::invoke_method_varargs(method_def, args); } - catch(...) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Loading of mesh was aborted"); - return NULL; + 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";} + throw Py::Exception(Part::PartExceptionOCCError, str); } - } PY_CATCH; + catch (const Base::Exception &e) { + throw Py::RuntimeError(e.what()); + } + catch (const std::exception &e) { + throw Py::RuntimeError(e.what()); + } + } + Py::Object open(const Py::Tuple& args) + { + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name)) + throw Py::Exception(); - Py_Return; -} + std::string EncodedName = std::string(Name); + PyMem_Free(Name); -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 { std::auto_ptr mesh(new FemMesh); mesh->read(EncodedName.c_str()); Base::FileInfo file(EncodedName.c_str()); @@ -115,47 +140,19 @@ static PyObject * open(PyObject *self, PyObject *args) pcFeature->FemMesh.setValuePtr(mesh.get()); (void)mesh.release(); pcFeature->purgeTouched(); - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object insert(const Py::Tuple& args) + { + char* Name; + const char* DocName = 0; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); -static PyObject * -show(PyObject *self, PyObject *args) -{ - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O!", &(FemMeshPy::Type), &pcObj)) // convert args: Python->C - return NULL; // NULL triggers exception + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { - App::Document *pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(); - - FemMeshPy* pShape = static_cast(pcObj); - Fem::FemMeshObject *pcFeature = (Fem::FemMeshObject *)pcDoc->addObject("Fem::FemMeshObject", "Mesh"); - // copy the data - //TopoShape* shape = new MeshObject(*pShape->getTopoShapeObjectPtr()); - pcFeature->FemMesh.setValue(*(pShape->getFemMeshPtr())); - pcDoc->recompute(); - } PY_CATCH; - - Py_Return; -} - - - - -static PyObject * importer(PyObject *self, PyObject *args) -{ - char* Name; - const char* DocName = 0; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - - PY_TRY { App::Document *pcDoc = 0; if (DocName) pcDoc = App::GetApplication().getDocument(DocName); @@ -176,378 +173,19 @@ static PyObject * importer(PyObject *self, PyObject *args) pcFeature->FemMesh.setValuePtr(mesh.get()); (void)mesh.release(); pcFeature->purgeTouched(); - } PY_CATCH; - Py_Return; -} + 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); -//static PyObject * import_NASTRAN(PyObject *self, PyObject *args) -//{ -// const char* filename_input, *filename_output; -// if (!PyArg_ParseTuple(args, "ss",&filename_input,&filename_output)) -// return NULL; -// -// PY_TRY { -// -// std::ifstream inputfile; -// -// //Für Debugoutput -// ofstream anOutput; -// anOutput.open("c:/time_measurement.txt"); -// time_t seconds1,seconds2; -// -// inputfile.open(filename_input); -// if (!inputfile.is_open()) //Exists...? -// { -// std::cerr << "File not found. Exiting..." << std::endl; -// return NULL; -// } -// -// //Return the line pointer to the beginning of the file -// inputfile.seekg(std::ifstream::beg); -// std::string line1,line2,temp; -// std::stringstream astream; -// std::vector tetra_element; -// std::vector element_id; -// element_id.clear(); -// std::vector > all_elements; -// std::vector >::iterator all_element_iterator; -// std::vector::iterator one_element_iterator; -// all_elements.clear(); -// MeshCore::MeshKernel aMesh; -// MeshCore::MeshPointArray vertices; -// vertices.clear(); -// MeshCore::MeshFacetArray faces; -// faces.clear(); -// MeshCore::MeshPoint current_node; -// -// seconds1 = time(NULL); -// do -// { -// std::getline(inputfile,line1); -// if (line1.size() == 0) continue; -// if (line1.find("GRID*")!= std::string::npos) //We found a Grid line -// { -// //Now lets extract the GRID Points = Nodes -// //As each GRID Line consists of two subsequent lines we have to -// //take care of that as well -// std::getline(inputfile,line2); -// //Extract X Value -// current_node.x = float(atof(line1.substr(40,56).c_str())); -// //Extract Y Value -// current_node.y = float(atof(line1.substr(56,72).c_str())); -// //Extract Z Value -// current_node.z = float(atof(line2.substr(8,24).c_str())); -// -// vertices.push_back(current_node); -// } -// else if (line1.find("CTETRA")!= std::string::npos) -// { -// tetra_element.clear(); -// //Lets extract the elements -// //As each Element Line consists of two subsequent lines as well -// //we have to take care of that -// //At a first step we only extract Quadratic Tetrahedral Elements -// std::getline(inputfile,line2); -// element_id.push_back(atoi(line1.substr(8,16).c_str())); -// tetra_element.push_back(atoi(line1.substr(24,32).c_str())); -// tetra_element.push_back(atoi(line1.substr(32,40).c_str())); -// tetra_element.push_back(atoi(line1.substr(40,48).c_str())); -// tetra_element.push_back(atoi(line1.substr(48,56).c_str())); -// tetra_element.push_back(atoi(line1.substr(56,64).c_str())); -// tetra_element.push_back(atoi(line1.substr(64,72).c_str())); -// tetra_element.push_back(atoi(line2.substr(8,16).c_str())); -// tetra_element.push_back(atoi(line2.substr(16,24).c_str())); -// tetra_element.push_back(atoi(line2.substr(24,32).c_str())); -// tetra_element.push_back(atoi(line2.substr(32,40).c_str())); -// -// all_elements.push_back(tetra_element); -// } -// -// } -// while (inputfile.good()); -// inputfile.close(); -// -// seconds2 = time(NULL); -// -// anOutput << seconds2-seconds1 <<" for Parsing the input file"<(2.0*M_PI/360.0);step_size=(2.0*M_PI/it_steps)) -// { -// for(alpha_x=angle_range_min_x;alpha_xCreateMesh(1, true); -// SMESHDS_Mesh* meshds = mesh->GetMeshDS(); -// -// MeshCore::MeshPointIterator anodeiterator(aMesh); -// int j=1; -// for(anodeiterator.Begin(); anodeiterator.More(); anodeiterator.Next()) -// { -// meshds->AddNodeWithID((*anodeiterator).x,(*anodeiterator).y,(*anodeiterator).z,j); -// j++; -// } -// -// for(unsigned int i=0;iAddVolumeWithID( -// meshds->FindNode(all_elements[i][0]), -// meshds->FindNode(all_elements[i][2]), -// meshds->FindNode(all_elements[i][1]), -// meshds->FindNode(all_elements[i][3]), -// meshds->FindNode(all_elements[i][6]), -// meshds->FindNode(all_elements[i][5]), -// meshds->FindNode(all_elements[i][4]), -// meshds->FindNode(all_elements[i][9]), -// meshds->FindNode(all_elements[i][7]), -// meshds->FindNode(all_elements[i][8]), -// element_id[i] -// ); -// } -// -// mesh->ExportUNV(filename_output); -// ////////////////////////////////////////////////////////////////////////////////////////// -// seconds2 = time(NULL); -// anOutput << seconds2-seconds1 << " seconds for the Mesh Export" << std::endl; -// -// //Output also to ABAQUS Input Format -// ofstream anABAQUS_Output; -// anABAQUS_Output.open("d:/abaqus_output.inp"); -// anABAQUS_Output << "*Node , NSET=Nall" << std::endl; -// j=1; -// for(anodeiterator.Begin(); anodeiterator.More(); anodeiterator.Next()) -// { -// anABAQUS_Output << j <<"," -// <<(*anodeiterator).x << "," -// <<(*anodeiterator).y << "," -// <<(*anodeiterator).z << std::endl; -// j++; -// } -// anABAQUS_Output << "*Element, TYPE=C3D10, ELSET=Eall" << std::endl; -// j=1; -// for(unsigned int i=0;iat(4)-1]-vertices[all_element_iterator->at(0)-1]; -// b = vertices[all_element_iterator->at(7)-1]-vertices[all_element_iterator->at(0)-1]; -// c = vertices[all_element_iterator->at(6)-1]-vertices[all_element_iterator->at(0)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// //5,9,8,7 -// a = vertices[all_element_iterator->at(8)-1]-vertices[all_element_iterator->at(4)-1]; -// b = vertices[all_element_iterator->at(7)-1]-vertices[all_element_iterator->at(4)-1]; -// c = vertices[all_element_iterator->at(6)-1]-vertices[all_element_iterator->at(4)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// //5,2,9,7 -// a = vertices[all_element_iterator->at(1)-1]-vertices[all_element_iterator->at(4)-1]; -// b = vertices[all_element_iterator->at(8)-1]-vertices[all_element_iterator->at(4)-1]; -// c = vertices[all_element_iterator->at(6)-1]-vertices[all_element_iterator->at(4)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// //2,6,9,7 -// a = vertices[all_element_iterator->at(5)-1]-vertices[all_element_iterator->at(1)-1]; -// b = vertices[all_element_iterator->at(8)-1]-vertices[all_element_iterator->at(1)-1]; -// c = vertices[all_element_iterator->at(6)-1]-vertices[all_element_iterator->at(1)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// //9,6,10,7 -// a = vertices[all_element_iterator->at(5)-1]-vertices[all_element_iterator->at(8)-1]; -// b = vertices[all_element_iterator->at(9)-1]-vertices[all_element_iterator->at(8)-1]; -// c = vertices[all_element_iterator->at(6)-1]-vertices[all_element_iterator->at(8)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// //6,3,10,7 -// a = vertices[all_element_iterator->at(2)-1]-vertices[all_element_iterator->at(5)-1]; -// b = vertices[all_element_iterator->at(9)-1]-vertices[all_element_iterator->at(5)-1]; -// c = vertices[all_element_iterator->at(6)-1]-vertices[all_element_iterator->at(5)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// //8,9,10,7 -// a = vertices[all_element_iterator->at(8)-1]-vertices[all_element_iterator->at(7)-1]; -// b = vertices[all_element_iterator->at(9)-1]-vertices[all_element_iterator->at(7)-1]; -// c = vertices[all_element_iterator->at(6)-1]-vertices[all_element_iterator->at(7)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// //8,9,10,4 -// a = vertices[all_element_iterator->at(8)-1]-vertices[all_element_iterator->at(7)-1]; -// b = vertices[all_element_iterator->at(9)-1]-vertices[all_element_iterator->at(7)-1]; -// c = vertices[all_element_iterator->at(3)-1]-vertices[all_element_iterator->at(7)-1]; -// a_b_product.x = a.y*b.z-b.y*a.z;a_b_product.y = a.z*b.x-b.z*a.x;a_b_product.z = a.x*b.y-b.x*a.y; -// volume += 1.0/6.0 * fabs((a_b_product.x * c.x)+ (a_b_product.y * c.y)+(a_b_product.z * c.z)); -// -// } -// seconds2=time(NULL); -// anOutput << seconds2-seconds1 << " seconds for Volume Calculation " << "Volumen " << volume/1000.0/1000.0/1000.0 << " in m^3" << std::endl; -// anOutput << "Volumen der BBox" << min_volumeBBOX/1000.0/1000.0/1000.0 << std::endl; -// anOutput << "Fly to Buy Ratio: " << min_volumeBBOX / volume << std::endl; -// anOutput.close(); -// -// } PY_CATCH; -// -// Py_Return; -//} - - -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); - - PY_TRY { Py::Sequence list(object); Base::Type meshId = Base::Type::fromName("Fem::FemMeshObject"); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { @@ -560,29 +198,46 @@ static PyObject * exporter(PyObject *self, PyObject *args) } } } - } PY_CATCH; - Py_Return; + 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); + + std::auto_ptr mesh(new FemMesh); + mesh->read(EncodedName.c_str()); + return Py::asObject(new FemMeshPy(mesh.release())); + } + Py::Object show(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O!", &(FemMeshPy::Type), &pcObj)) + throw Py::Exception(); + + App::Document *pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(); + + FemMeshPy* pShape = static_cast(pcObj); + Fem::FemMeshObject *pcFeature = (Fem::FemMeshObject *)pcDoc->addObject("Fem::FemMeshObject", "Mesh"); + // copy the data + //TopoShape* shape = new MeshObject(*pShape->getTopoShapeObjectPtr()); + pcFeature->FemMesh.setValue(*(pShape->getFemMeshPtr())); + pcDoc->recompute(); + + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -// ---------------------------------------------------------------------------- - -PyDoc_STRVAR(open_doc, -"open(string) -- Create a new document and a Mesh::Import feature to load the file into the document."); - -PyDoc_STRVAR(inst_doc, -"insert(string|mesh,[string]) -- Load or insert a mesh into the given or active document."); - -PyDoc_STRVAR(export_doc, -"export(list,string) -- Export a list of objects into a single file."); - -/* registration table */ -struct PyMethodDef Fem_methods[] = { - {"open" ,open , METH_VARARGS, open_doc}, - {"insert" ,importer, METH_VARARGS, inst_doc}, - {"export" ,exporter, METH_VARARGS, export_doc}, - {"read" ,read, Py_NEWARGS, "Read a mesh from a file and returns a Mesh object."}, - {"show" ,show ,METH_VARARGS, - "show(shape) -- Add the shape to the active document or create one if no document exists."}, - {NULL, NULL} /* sentinel */ -}; +} // namespace Fem diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index 85a8603ebe..c7491a03fa 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -63,20 +63,20 @@ void loadFemResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef FemGui_Import_methods[]; +namespace FemGui { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void FemGuiExport initFemGui() +PyMODINIT_FUNC initFemGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); return; } - (void) Py_InitModule("FemGui", FemGui_Import_methods); /* mod name, table ptr */ + (void) FemGui::initModule(); Base::Console().Log("Loading GUI of Fem module... done\n"); // instantiating the commands @@ -112,5 +112,3 @@ void FemGuiExport initFemGui() // add resources and reloads the translators loadFemResource(); } - -} // extern "C" { diff --git a/src/Mod/Fem/Gui/AppFemGuiPy.cpp b/src/Mod/Fem/Gui/AppFemGuiPy.cpp index 4ad537c18a..4d14971277 100755 --- a/src/Mod/Fem/Gui/AppFemGuiPy.cpp +++ b/src/Mod/Fem/Gui/AppFemGuiPy.cpp @@ -27,6 +27,9 @@ # include #endif +#include +#include + #include #include #include @@ -41,50 +44,80 @@ #include "AbaqusHighlighter.h" -/* module functions */ -static PyObject * setActiveAnalysis(PyObject *self, PyObject *args) +namespace FemGui { +class Module : public Py::ExtensionModule { - if (FemGui::ActiveAnalysisObserver::instance()->hasActiveObject()) { - FemGui::ActiveAnalysisObserver::instance()->highlightActiveObject(Gui::Blue,false); - FemGui::ActiveAnalysisObserver::instance()->setActiveObject(0); +public: + Module() : Py::ExtensionModule("FemGui") + { + add_varargs_method("setActiveAnalysis",&Module::setActiveAnalysis, + "setActiveAnalysis(AnalysisObject) -- Set the Analysis object in work." + ); + add_varargs_method("getActiveAnalysis",&Module::getActiveAnalysis, + "getActiveAnalysis() -- Returns the Analysis object in work." + ); + add_varargs_method("open",&Module::open, + "open(string) -- Opens an Abaqus file in a text editor." + ); + add_varargs_method("insert",&Module::open, + "insert(string,string) -- Opens an Abaqus file in a text editor." + ); + initialize("This module is the FemGui module."); // register with Python } - PyObject *object=0; - if (PyArg_ParseTuple(args,"|O!",&(App::DocumentObjectPy::Type), &object)&& object) { - App::DocumentObject* obj = static_cast(object)->getDocumentObjectPtr(); - if (!obj || !obj->getTypeId().isDerivedFrom(Fem::FemAnalysis::getClassTypeId())){ - PyErr_SetString(Base::BaseExceptionFreeCADError, "Active Analysis object have to be of type Fem::FemAnalysis!"); - return 0; + 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 Base::Exception &e) { + throw Py::RuntimeError(e.what()); + } + catch (const std::exception &e) { + throw Py::RuntimeError(e.what()); + } + } + Py::Object setActiveAnalysis(const Py::Tuple& args) + { + if (FemGui::ActiveAnalysisObserver::instance()->hasActiveObject()) { + FemGui::ActiveAnalysisObserver::instance()->highlightActiveObject(Gui::Blue,false); + FemGui::ActiveAnalysisObserver::instance()->setActiveObject(0); } - // get the gui document of the Analysis Item - FemGui::ActiveAnalysisObserver::instance()->setActiveObject(static_cast(obj)); - FemGui::ActiveAnalysisObserver::instance()->highlightActiveObject(Gui::Blue,true); + PyObject *object=0; + if (PyArg_ParseTuple(args.ptr(),"|O!",&(App::DocumentObjectPy::Type), &object)&& object) { + App::DocumentObject* obj = static_cast(object)->getDocumentObjectPtr(); + if (!obj || !obj->getTypeId().isDerivedFrom(Fem::FemAnalysis::getClassTypeId())){ + throw Py::Exception(Base::BaseExceptionFreeCADError, "Active Analysis object have to be of type Fem::FemAnalysis!"); + } + + // get the gui document of the Analysis Item + FemGui::ActiveAnalysisObserver::instance()->setActiveObject(static_cast(obj)); + FemGui::ActiveAnalysisObserver::instance()->highlightActiveObject(Gui::Blue,true); + } + + return Py::None(); } - - Py_Return; -} - -/* module functions */ -static PyObject * getActiveAnalysis(PyObject *self, PyObject *args) -{ - if (FemGui::ActiveAnalysisObserver::instance()->hasActiveObject()) { - return FemGui::ActiveAnalysisObserver::instance()->getActiveObject()->getPyObject(); + Py::Object getActiveAnalysis(const Py::Tuple& args) + { + if (FemGui::ActiveAnalysisObserver::instance()->hasActiveObject()) { + return Py::asObject(FemGui::ActiveAnalysisObserver::instance()->getActiveObject()->getPyObject()); + } + return Py::None(); } + Py::Object open(const Py::Tuple& args) + { + char* Name; + const char* DocName; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); - Py_Return; -} + std::string EncodedName = std::string(Name); + PyMem_Free(Name); -/* module functions */ -static PyObject * open(PyObject *self, PyObject *args) -{ - char* Name; - const char* DocName; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - PY_TRY { QString fileName = QString::fromUtf8(EncodedName.c_str()); QFileInfo fi; fi.setFile(fileName); @@ -93,7 +126,7 @@ static PyObject * open(PyObject *self, PyObject *args) for (QList::Iterator it = views.begin(); it != views.end(); ++it) { if ((*it)->fileName() == fileName) { (*it)->setFocus(); - Py_Return; + return Py::None(); } } @@ -111,22 +144,14 @@ static PyObject * open(PyObject *self, PyObject *args) font.setFamily(QString::fromLatin1("Arial")); editor->setFont(font); } - } PY_CATCH; - Py_Return; + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } - - -/* registration table */ -struct PyMethodDef FemGui_Import_methods[] = { - {"setActiveAnalysis" ,setActiveAnalysis ,METH_VARARGS, - "setActiveAnalysis(AnalysisObject) -- Set the Analysis object in work."}, - {"getActiveAnalysis" ,getActiveAnalysis ,METH_VARARGS, - "getActiveAnalysis() -- Returns the Analysis object in work."}, - {"open" ,open ,METH_VARARGS, - "open(string) -- Opens an Abaqus file in a text editor."}, - {"insert" ,open ,METH_VARARGS, - "insert(string,string) -- Opens an Abaqus file in a text editor."}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace FemGui diff --git a/src/Mod/Image/App/AppImage.cpp b/src/Mod/Image/App/AppImage.cpp index 8859b84e94..d77b5de567 100644 --- a/src/Mod/Image/App/AppImage.cpp +++ b/src/Mod/Image/App/AppImage.cpp @@ -14,24 +14,41 @@ # include #endif +#include +#include + #include #include "ImagePlane.h" -/* registration table */ -static struct PyMethodDef Image_methods[] = { - {NULL, NULL} /* end of table marker */ +namespace Image { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("Image") + { + initialize("This module is the Image module."); // register with Python + } + + virtual ~Module() {} + +private: }; +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace Image + /* Python entry */ -extern "C" { -void ImageExport initImage() { - (void) Py_InitModule("Image", Image_methods); /* mod name, table ptr */ +PyMODINIT_FUNC initImage() +{ + (void) Image::initModule(); Base::Console().Log("Loading Image module... done\n"); Image::ImagePlane::init(); return; } - -} // extern "C" diff --git a/src/Mod/Image/Gui/AppImageGui.cpp b/src/Mod/Image/Gui/AppImageGui.cpp index 6ca8c54ff3..182ada2c49 100644 --- a/src/Mod/Image/Gui/AppImageGui.cpp +++ b/src/Mod/Image/Gui/AppImageGui.cpp @@ -31,20 +31,20 @@ void loadImageResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef ImageGui_Import_methods[]; +namespace ImageGui { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void ImageGuiExport initImageGui() +PyMODINIT_FUNC initImageGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); return; } - (void) Py_InitModule("ImageGui", ImageGui_Import_methods); /* mod name, table ptr */ + (void) ImageGui::initModule(); Base::Console().Log("Loading GUI of Image module... done\n"); // instantiating the commands @@ -56,5 +56,3 @@ void ImageGuiExport initImageGui() // add resources and reloads the translators loadImageResource(); } - -} // extern "C" { diff --git a/src/Mod/Image/Gui/AppImageGuiPy.cpp b/src/Mod/Image/Gui/AppImageGuiPy.cpp index f9fef2a3bf..261ae29e6c 100644 --- a/src/Mod/Image/Gui/AppImageGuiPy.cpp +++ b/src/Mod/Image/Gui/AppImageGuiPy.cpp @@ -27,6 +27,9 @@ # include #endif +#include +#include + #include "ImageView.h" #include @@ -36,21 +39,32 @@ #include #include -using namespace ImageGui; - - -/* module functions */ -static PyObject * -open(PyObject *self, PyObject *args) +namespace ImageGui { +class Module : public Py::ExtensionModule { - char* Name; - const char* DocName=0; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("ImageGui") + { + add_varargs_method("open",&Module::open + ); + add_varargs_method("insert",&Module::open + ); + initialize("This module is the ImageGui module."); // register with Python + } + + virtual ~Module() {} + +private: + Py::Object open(const Py::Tuple& args) + { + char* Name; + const char* DocName=0; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { QString fileName = QString::fromUtf8(EncodedName.c_str()); QFileInfo file(fileName); @@ -73,8 +87,9 @@ open(PyObject *self, PyObject *args) } } } - else - Py_Error(PyExc_IOError, "Could not load image file"); + else { + throw Py::Exception(PyExc_IOError, "Could not load image file"); + } // Displaying the image in a view. // This ImageView object takes ownership of the pixel data (in 'pointImageTo') so we don't need to delete it here @@ -85,22 +100,13 @@ open(PyObject *self, PyObject *args) Gui::getMainWindow()->addWindow( iView ); iView->pointImageTo((void *)pPixelData, (unsigned long)imageq.width(), (unsigned long)imageq.height(), format, 0, true); - } PY_CATCH; - - Py_Return; -} - - -/* module functions */ -static PyObject * -insert(PyObject *self, PyObject *args) -{ - return open(self, args); -} - -/* registration table */ -struct PyMethodDef ImageGui_Import_methods[] = { - {"open" ,open , 1}, /* method name, C func ptr, always-tuple */ - {"insert" ,insert, 1}, - {NULL, NULL} /* end of table marker */ + return Py::None(); + } }; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace ImageGui diff --git a/src/Mod/Import/App/AppImport.cpp b/src/Mod/Import/App/AppImport.cpp index cd6c6e484c..d08a3fc8c5 100644 --- a/src/Mod/Import/App/AppImport.cpp +++ b/src/Mod/Import/App/AppImport.cpp @@ -32,17 +32,13 @@ #include "StepShapePy.h" #include "StepShape.h" +namespace Import { + extern PyObject* initModule(); +} -/* registration table */ -extern struct PyMethodDef Import_Import_methods[]; - -PyDoc_STRVAR(module_doc, -"This module is about import/export files formates.\n" -"\n"); -extern "C" { -void ImportExport initImport() +PyMODINIT_FUNC initImport() { - PyObject* importModule = Py_InitModule3("Import", Import_Import_methods, module_doc); /* mod name, table ptr */ + PyObject* importModule = Import::initModule(); try { Base::Interpreter().loadModule("Part"); @@ -53,13 +49,10 @@ void ImportExport initImport() } // add mesh elements - Base::Interpreter().addType(&Import::StepShapePy ::Type,importModule,"StepShape"); + Base::Interpreter().addType(&Import::StepShapePy ::Type, importModule, "StepShape"); // init Type system //Import::StepShape ::init(); Base::Console().Log("Loading Import module... done\n"); } - - -} // extern "C" { diff --git a/src/Mod/Import/App/AppImportPy.cpp b/src/Mod/Import/App/AppImportPy.cpp index a3326d1bf5..f7ea1fce54 100644 --- a/src/Mod/Import/App/AppImportPy.cpp +++ b/src/Mod/Import/App/AppImportPy.cpp @@ -48,6 +48,9 @@ # include #endif +#include +#include + #include "ImportOCAF.h" #include #include @@ -60,233 +63,244 @@ #include #include -/* module functions */ -static PyObject * importer(PyObject *self, PyObject *args) +namespace Import { +class Module : public Py::ExtensionModule { - char* Name; - char* DocName=0; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string Utf8Name = std::string(Name); - PyMem_Free(Name); - std::string name8bit = Part::encodeFilename(Utf8Name); +public: + Module() : Py::ExtensionModule("Import") + { + add_varargs_method("open",&Module::importer, + "open(string) -- Open the file and create a new document." + ); + add_varargs_method("insert",&Module::importer, + "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." + ); + initialize("This module is the Import module."); // register with Python + } - PY_TRY { - //Base::Console().Log("Insert in Part with %s",Name); - Base::FileInfo file(Utf8Name.c_str()); + virtual ~Module() {} - App::Document *pcDoc = 0; - if (DocName) { - pcDoc = App::GetApplication().getDocument(DocName); - } - if (!pcDoc) { - pcDoc = App::GetApplication().newDocument("Unnamed"); - } +private: + Py::Object importer(const Py::Tuple& args) + { + char* Name; + char* DocName=0; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); - Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); - Handle(TDocStd_Document) hDoc; - hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); + std::string Utf8Name = std::string(Name); + PyMem_Free(Name); + std::string name8bit = Part::encodeFilename(Utf8Name); - if (file.hasExtension("stp") || file.hasExtension("step")) { - try { - STEPCAFControl_Reader aReader; - aReader.SetColorMode(true); - aReader.SetNameMode(true); - aReader.SetLayerMode(true); - if (aReader.ReadFile((Standard_CString)(name8bit.c_str())) != IFSelect_RetDone) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "cannot read STEP file"); - return 0; + try { + //Base::Console().Log("Insert in Part with %s",Name); + Base::FileInfo file(Utf8Name.c_str()); + + App::Document *pcDoc = 0; + if (DocName) { + pcDoc = App::GetApplication().getDocument(DocName); + } + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument("Unnamed"); + } + + Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); + Handle(TDocStd_Document) hDoc; + hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); + + if (file.hasExtension("stp") || file.hasExtension("step")) { + try { + STEPCAFControl_Reader aReader; + aReader.SetColorMode(true); + aReader.SetNameMode(true); + aReader.SetLayerMode(true); + if (aReader.ReadFile((Standard_CString)(name8bit.c_str())) != IFSelect_RetDone) { + throw Py::Exception(PyExc_IOError, "cannot read STEP file"); + } + + Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); + aReader.Reader().WS()->MapReader()->SetProgress(pi); + pi->NewScope(100, "Reading STEP file..."); + pi->Show(); + aReader.Transfer(hDoc); + pi->EndScope(); } + catch (OSD_Exception) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + Base::Console().Error("%s\n", e->GetMessageString()); + Base::Console().Message("Try to load STEP file without colors...\n"); - Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); - aReader.Reader().WS()->MapReader()->SetProgress(pi); - pi->NewScope(100, "Reading STEP file..."); - pi->Show(); - aReader.Transfer(hDoc); - pi->EndScope(); - } - catch (OSD_Exception) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - Base::Console().Error("%s\n", e->GetMessageString()); - Base::Console().Message("Try to load STEP file without colors...\n"); - - Part::ImportStepParts(pcDoc,Utf8Name.c_str()); - pcDoc->recompute(); - } - } - else if (file.hasExtension("igs") || file.hasExtension("iges")) { - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("IGES"); - - try { - IGESControl_Controller::Init(); - IGESCAFControl_Reader aReader; - // http://www.opencascade.org/org/forum/thread_20603/?forum=3 - aReader.SetReadVisible(hGrp->GetBool("SkipBlankEntities", true) - ? Standard_True : Standard_False); - aReader.SetColorMode(true); - aReader.SetNameMode(true); - aReader.SetLayerMode(true); - if (aReader.ReadFile((Standard_CString)(name8bit.c_str())) != IFSelect_RetDone) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "cannot read IGES file"); - return 0; + Part::ImportStepParts(pcDoc,Utf8Name.c_str()); + pcDoc->recompute(); } - - Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); - aReader.WS()->MapReader()->SetProgress(pi); - pi->NewScope(100, "Reading IGES file..."); - pi->Show(); - aReader.Transfer(hDoc); - pi->EndScope(); } - catch (OSD_Exception) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - Base::Console().Error("%s\n", e->GetMessageString()); - Base::Console().Message("Try to load IGES file without colors...\n"); + else if (file.hasExtension("igs") || file.hasExtension("iges")) { + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("IGES"); - Part::ImportIgesParts(pcDoc,Utf8Name.c_str()); - pcDoc->recompute(); + try { + IGESControl_Controller::Init(); + IGESCAFControl_Reader aReader; + // http://www.opencascade.org/org/forum/thread_20603/?forum=3 + aReader.SetReadVisible(hGrp->GetBool("SkipBlankEntities", true) + ? Standard_True : Standard_False); + aReader.SetColorMode(true); + aReader.SetNameMode(true); + aReader.SetLayerMode(true); + if (aReader.ReadFile((Standard_CString)(name8bit.c_str())) != IFSelect_RetDone) { + throw Py::Exception(PyExc_IOError, "cannot read IGES file"); + } + + Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); + aReader.WS()->MapReader()->SetProgress(pi); + pi->NewScope(100, "Reading IGES file..."); + pi->Show(); + aReader.Transfer(hDoc); + pi->EndScope(); + } + catch (OSD_Exception) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + Base::Console().Error("%s\n", e->GetMessageString()); + Base::Console().Message("Try to load IGES file without colors...\n"); + + Part::ImportIgesParts(pcDoc,Utf8Name.c_str()); + pcDoc->recompute(); + } + } + else { + throw Py::Exception(Base::BaseExceptionFreeCADError, "no supported file format"); } - } - else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "no supported file format"); - return 0; - } #if 1 - Import::ImportOCAF ocaf(hDoc, pcDoc, file.fileNamePure()); - ocaf.loadShapes(); + Import::ImportOCAF ocaf(hDoc, pcDoc, file.fileNamePure()); + ocaf.loadShapes(); #else - Import::ImportXCAF xcaf(hDoc, pcDoc, file.fileNamePure()); - xcaf.loadShapes(); + Import::ImportXCAF xcaf(hDoc, pcDoc, file.fileNamePure()); + xcaf.loadShapes(); #endif - pcDoc->recompute(); + pcDoc->recompute(); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(Base::BaseExceptionFreeCADError, e->GetMessageString()); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + return Py::None(); } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(Base::BaseExceptionFreeCADError, e->GetMessageString()); - return 0; - } - PY_CATCH + Py::Object exporter(const Py::Tuple& args) + { + PyObject* object; + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "Oet",&object,"utf-8",&Name)) + throw Py::Exception(); - Py_Return; -} + std::string Utf8Name = std::string(Name); + PyMem_Free(Name); + std::string name8bit = Part::encodeFilename(Utf8Name); -static PyObject * open(PyObject *self, PyObject *args) -{ - return importer(self, args); -} + try { + Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); + Handle(TDocStd_Document) hDoc; + hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); + Import::ExportOCAF ocaf(hDoc); -static PyObject * exporter(PyObject *self, PyObject *args) -{ - PyObject* object; - char* Name; - if (!PyArg_ParseTuple(args, "Oet",&object,"utf-8",&Name)) - return NULL; - std::string Utf8Name = std::string(Name); - PyMem_Free(Name); - std::string name8bit = Part::encodeFilename(Utf8Name); - - PY_TRY { - Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); - Handle(TDocStd_Document) hDoc; - hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); - Import::ExportOCAF ocaf(hDoc); - - 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); - std::vector colors; - ocaf.saveShape(part, colors); - } - else { - Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue()); - } - } - else if (PyTuple_Check(item) && PyTuple_Size(item) == 2) { - Py::Tuple tuple(*it); - Py::Object item0 = tuple.getItem(0); - Py::Object item1 = tuple.getItem(1); - if (PyObject_TypeCheck(item0.ptr(), &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(item0.ptr())->getDocumentObjectPtr(); + 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); - App::PropertyColorList colors; - colors.setPyObject(item1.ptr()); - ocaf.saveShape(part, colors.getValues()); + std::vector colors; + ocaf.saveShape(part, colors); } else { Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue()); } } + else if (PyTuple_Check(item) && PyTuple_Size(item) == 2) { + Py::Tuple tuple(*it); + Py::Object item0 = tuple.getItem(0); + Py::Object item1 = tuple.getItem(1); + if (PyObject_TypeCheck(item0.ptr(), &(App::DocumentObjectPy::Type))) { + App::DocumentObject* obj = static_cast(item0.ptr())->getDocumentObjectPtr(); + if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { + Part::Feature* part = static_cast(obj); + App::PropertyColorList colors; + colors.setPyObject(item1.ptr()); + ocaf.saveShape(part, colors.getValues()); + } + else { + Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue()); + } + } + } } - } - Base::FileInfo file(Utf8Name.c_str()); - if (file.hasExtension("stp") || file.hasExtension("step")) { - //Interface_Static::SetCVal("write.step.schema", "AP214IS"); - STEPCAFControl_Writer writer; - writer.Transfer(hDoc, STEPControl_AsIs); + Base::FileInfo file(Utf8Name.c_str()); + if (file.hasExtension("stp") || file.hasExtension("step")) { + //Interface_Static::SetCVal("write.step.schema", "AP214IS"); + STEPCAFControl_Writer writer; + writer.Transfer(hDoc, STEPControl_AsIs); - // edit STEP header + // edit STEP header #if OCC_VERSION_HEX >= 0x060500 - APIHeaderSection_MakeHeader makeHeader(writer.ChangeWriter().Model()); + APIHeaderSection_MakeHeader makeHeader(writer.ChangeWriter().Model()); #else - APIHeaderSection_MakeHeader makeHeader(writer.Writer().Model()); + APIHeaderSection_MakeHeader makeHeader(writer.Writer().Model()); #endif - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("STEP"); + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("STEP"); - makeHeader.SetName(new TCollection_HAsciiString((const Standard_CString)Utf8Name.c_str())); - makeHeader.SetAuthorValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Author", "Author").c_str())); - makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Company").c_str())); - makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::GetApplication().getExecutableName())); - makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model")); - IFSelect_ReturnStatus ret = writer.Write(name8bit.c_str()); - if (ret == IFSelect_RetError || ret == IFSelect_RetFail || ret == IFSelect_RetStop) { - PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); - return 0; + makeHeader.SetName(new TCollection_HAsciiString((const Standard_CString)Utf8Name.c_str())); + makeHeader.SetAuthorValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Author", "Author").c_str())); + makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Company").c_str())); + makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::GetApplication().getExecutableName())); + makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model")); + IFSelect_ReturnStatus ret = writer.Write(name8bit.c_str()); + if (ret == IFSelect_RetError || ret == IFSelect_RetFail || ret == IFSelect_RetStop) { + PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); + throw Py::Exception(); + } + } + else if (file.hasExtension("igs") || file.hasExtension("iges")) { + IGESControl_Controller::Init(); + IGESCAFControl_Writer writer; + IGESData_GlobalSection header = writer.Model()->GlobalSection(); + header.SetAuthorName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.author"))); + header.SetCompanyName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.company"))); + header.SetSendName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.product"))); + writer.Model()->SetGlobalSection(header); + writer.Transfer(hDoc); + Standard_Boolean ret = writer.Write(name8bit.c_str()); + if (!ret) { + PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); + throw Py::Exception(); + } } } - else if (file.hasExtension("igs") || file.hasExtension("iges")) { - IGESControl_Controller::Init(); - IGESCAFControl_Writer writer; - IGESData_GlobalSection header = writer.Model()->GlobalSection(); - header.SetAuthorName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.author"))); - header.SetCompanyName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.company"))); - header.SetSendName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.product"))); - writer.Model()->SetGlobalSection(header); - writer.Transfer(hDoc); - Standard_Boolean ret = writer.Write(name8bit.c_str()); - if (!ret) { - PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); - return 0; - } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(Base::BaseExceptionFreeCADError, e->GetMessageString()); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); } - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(Base::BaseExceptionFreeCADError, e->GetMessageString()); - return 0; - } - PY_CATCH - Py_Return; + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef Import_Import_methods[] = { - {"open" ,open ,METH_VARARGS, - "open(string) -- Open the file and create a new document."}, - {"insert" ,importer ,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."}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace Import diff --git a/src/Mod/Import/Gui/AppImportGui.cpp b/src/Mod/Import/Gui/AppImportGui.cpp index 55cd2fae8d..9c5bc6cfb2 100644 --- a/src/Mod/Import/Gui/AppImportGui.cpp +++ b/src/Mod/Import/Gui/AppImportGui.cpp @@ -39,17 +39,17 @@ void CreateImportCommands(void); -/* registration table */ -extern struct PyMethodDef ImportGui_Import_methods[]; +namespace ImportGui { +extern PyObject* initModule(); +} -extern "C" { -void ImportGuiExport initImportGui() +PyMODINIT_FUNC initImportGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); return; } - (void) Py_InitModule("ImportGui", ImportGui_Import_methods); /* mod name, table ptr */ + (void)ImportGui::initModule(); Base::Console().Log("Loading GUI of Import module... done\n"); try { @@ -63,5 +63,3 @@ void ImportGuiExport initImportGui() CreateImportCommands(); ImportGui::Workbench::init(); } - -} // extern "C" { diff --git a/src/Mod/Import/Gui/AppImportGuiPy.cpp b/src/Mod/Import/Gui/AppImportGuiPy.cpp index 3321efe1e0..57987b0e02 100644 --- a/src/Mod/Import/Gui/AppImportGuiPy.cpp +++ b/src/Mod/Import/Gui/AppImportGuiPy.cpp @@ -68,6 +68,9 @@ # endif #endif +#include +#include + #include #include #include @@ -83,228 +86,6 @@ #include #include -class ImportOCAFExt : public Import::ImportOCAF -{ -public: - ImportOCAFExt(Handle_TDocStd_Document h, App::Document* d, const std::string& name) - : ImportOCAF(h, d, name) - { - } - -private: - void applyColors(Part::Feature* part, const std::vector& colors) - { - Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part); - if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) { - static_cast(vp)->ShapeColor.setValue(colors.front()); - static_cast(vp)->DiffuseColor.setValues(colors); - } - } -}; - -/* module functions */ - -static PyObject * importer(PyObject *self, PyObject *args) -{ - char* Name; - char* DocName=0; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return 0; - std::string Utf8Name = std::string(Name); - PyMem_Free(Name); - std::string name8bit = Part::encodeFilename(Utf8Name); - - PY_TRY { - //Base::Console().Log("Insert in Part with %s",Name); - Base::FileInfo file(Utf8Name.c_str()); - - App::Document *pcDoc = 0; - if (DocName) { - pcDoc = App::GetApplication().getDocument(DocName); - } - if (!pcDoc) { - pcDoc = App::GetApplication().newDocument("Unnamed"); - } - - Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); - Handle(TDocStd_Document) hDoc; - hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); - - if (file.hasExtension("stp") || file.hasExtension("step")) { - try { - STEPCAFControl_Reader aReader; - aReader.SetColorMode(true); - aReader.SetNameMode(true); - aReader.SetLayerMode(true); - if (aReader.ReadFile((const char*)name8bit.c_str()) != IFSelect_RetDone) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "cannot read STEP file"); - return 0; - } - - Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); - aReader.Reader().WS()->MapReader()->SetProgress(pi); - pi->NewScope(100, "Reading STEP file..."); - pi->Show(); - aReader.Transfer(hDoc); - pi->EndScope(); - } - catch (OSD_Exception) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - Base::Console().Error("%s\n", e->GetMessageString()); - Base::Console().Message("Try to load STEP file without colors...\n"); - - Part::ImportStepParts(pcDoc,Utf8Name.c_str()); - pcDoc->recompute(); - } - } - else if (file.hasExtension("igs") || file.hasExtension("iges")) { - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("IGES"); - - try { - IGESControl_Controller::Init(); - IGESCAFControl_Reader aReader; - // http://www.opencascade.org/org/forum/thread_20603/?forum=3 - aReader.SetReadVisible(hGrp->GetBool("SkipBlankEntities", true) - ? Standard_True : Standard_False); - aReader.SetColorMode(true); - aReader.SetNameMode(true); - aReader.SetLayerMode(true); - if (aReader.ReadFile((const char*)name8bit.c_str()) != IFSelect_RetDone) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "cannot read IGES file"); - return 0; - } - - Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); - aReader.WS()->MapReader()->SetProgress(pi); - pi->NewScope(100, "Reading IGES file..."); - pi->Show(); - aReader.Transfer(hDoc); - pi->EndScope(); - } - catch (OSD_Exception) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - Base::Console().Error("%s\n", e->GetMessageString()); - Base::Console().Message("Try to load IGES file without colors...\n"); - - Part::ImportIgesParts(pcDoc,Utf8Name.c_str()); - pcDoc->recompute(); - } - } - else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "no supported file format"); - return 0; - } - - ImportOCAFExt ocaf(hDoc, pcDoc, file.fileNamePure()); - ocaf.loadShapes(); - pcDoc->recompute(); - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(Base::BaseExceptionFreeCADError, e->GetMessageString()); - return 0; - } - PY_CATCH - - Py_Return; -} - -static PyObject * open(PyObject *self, PyObject *args) -{ - return importer(self, args); -} - -static PyObject * exporter(PyObject *self, PyObject *args) -{ - PyObject* object; - char* Name; - if (!PyArg_ParseTuple(args, "Oet",&object,"utf-8",&Name)) - return NULL; - std::string Utf8Name = std::string(Name); - PyMem_Free(Name); - std::string name8bit = Part::encodeFilename(Utf8Name); - - PY_TRY { - Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); - Handle(TDocStd_Document) hDoc; - hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); - Import::ExportOCAF ocaf(hDoc); - - 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); - std::vector colors; - Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part); - if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) { - colors = static_cast(vp)->DiffuseColor.getValues(); - if (colors.empty()) - colors.push_back(static_cast(vp)->ShapeColor.getValue()); - } - ocaf.saveShape(part, colors); - } - else { - Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue()); - } - } - } - - Base::FileInfo file(Utf8Name.c_str()); - if (file.hasExtension("stp") || file.hasExtension("step")) { - //Interface_Static::SetCVal("write.step.schema", "AP214IS"); - STEPCAFControl_Writer writer; - writer.Transfer(hDoc, STEPControl_AsIs); - - // edit STEP header -#if OCC_VERSION_HEX >= 0x060500 - APIHeaderSection_MakeHeader makeHeader(writer.ChangeWriter().Model()); -#else - APIHeaderSection_MakeHeader makeHeader(writer.Writer().Model()); -#endif - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("STEP"); - - makeHeader.SetName(new TCollection_HAsciiString((const Standard_CString)(Utf8Name.c_str()))); - makeHeader.SetAuthorValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Author", "Author").c_str())); - makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Company").c_str())); - makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::GetApplication().getExecutableName())); - makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model")); - IFSelect_ReturnStatus ret = writer.Write((const char*)name8bit.c_str()); - if (ret == IFSelect_RetError || ret == IFSelect_RetFail || ret == IFSelect_RetStop) { - PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); - return 0; - } - } - else if (file.hasExtension("igs") || file.hasExtension("iges")) { - IGESControl_Controller::Init(); - IGESCAFControl_Writer writer; - IGESData_GlobalSection header = writer.Model()->GlobalSection(); - header.SetAuthorName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.author"))); - header.SetCompanyName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.company"))); - header.SetSendName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.product"))); - writer.Model()->SetGlobalSection(header); - writer.Transfer(hDoc); - Standard_Boolean ret = writer.Write((const char*)name8bit.c_str()); - if (!ret) { - PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); - return 0; - } - } - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(Base::BaseExceptionFreeCADError, e->GetMessageString()); - return 0; - } - PY_CATCH - - Py_Return; -} - #include #include #include @@ -483,109 +264,343 @@ void OCAFBrowser::load(const TDF_Label& label, QTreeWidgetItem* item, const QStr } } -static PyObject * ocaf(PyObject *self, PyObject *args) +class ImportOCAFExt : public Import::ImportOCAF { - const char* Name; - if (!PyArg_ParseTuple(args, "s",&Name)) - return 0; +public: + ImportOCAFExt(Handle_TDocStd_Document h, App::Document* d, const std::string& name) + : ImportOCAF(h, d, name) + { + } - PY_TRY { - //Base::Console().Log("Insert in Part with %s",Name); - Base::FileInfo file(Name); +private: + void applyColors(Part::Feature* part, const std::vector& colors) + { + Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part); + if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) { + static_cast(vp)->ShapeColor.setValue(colors.front()); + static_cast(vp)->DiffuseColor.setValues(colors); + } + } +}; - Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); - Handle(TDocStd_Document) hDoc; - hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); +namespace ImportGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("ImportGui") + { + add_varargs_method("open",&Module::open, + "open(string) -- Open the file and create a new 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("ocaf",&Module::ocaf, + "ocaf(string) -- Browse the ocaf structure." + ); + initialize("This module is the ImportGui module."); // register with Python + } - if (file.hasExtension("stp") || file.hasExtension("step")) { - STEPCAFControl_Reader aReader; - aReader.SetColorMode(true); - aReader.SetNameMode(true); - aReader.SetLayerMode(true); - if (aReader.ReadFile((Standard_CString)Name) != IFSelect_RetDone) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "cannot read STEP file"); - return 0; + virtual ~Module() {} + +private: + Py::Object open(const Py::Tuple& args) + { + return insert(args); + } + Py::Object insert(const Py::Tuple& args) + { + char* Name; + char* DocName=0; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); + + std::string Utf8Name = std::string(Name); + PyMem_Free(Name); + std::string name8bit = Part::encodeFilename(Utf8Name); + + try { + //Base::Console().Log("Insert in Part with %s",Name); + Base::FileInfo file(Utf8Name.c_str()); + + App::Document *pcDoc = 0; + if (DocName) { + pcDoc = App::GetApplication().getDocument(DocName); + } + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument("Unnamed"); } - Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); - aReader.Reader().WS()->MapReader()->SetProgress(pi); - pi->NewScope(100, "Reading STEP file..."); - pi->Show(); - aReader.Transfer(hDoc); - pi->EndScope(); - } - else if (file.hasExtension("igs") || file.hasExtension("iges")) { - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("IGES"); - IGESControl_Controller::Init(); - IGESCAFControl_Reader aReader; - // http://www.opencascade.org/org/forum/thread_20603/?forum=3 - aReader.SetReadVisible(hGrp->GetBool("SkipBlankEntities", true) - ? Standard_True : Standard_False); - aReader.SetColorMode(true); - aReader.SetNameMode(true); - aReader.SetLayerMode(true); - if (aReader.ReadFile((Standard_CString)Name) != IFSelect_RetDone) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "cannot read IGES file"); - return 0; + Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); + Handle(TDocStd_Document) hDoc; + hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); + + if (file.hasExtension("stp") || file.hasExtension("step")) { + try { + STEPCAFControl_Reader aReader; + aReader.SetColorMode(true); + aReader.SetNameMode(true); + aReader.SetLayerMode(true); + if (aReader.ReadFile((const char*)name8bit.c_str()) != IFSelect_RetDone) { + throw Py::Exception(PyExc_IOError, "cannot read STEP file"); + } + + Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); + aReader.Reader().WS()->MapReader()->SetProgress(pi); + pi->NewScope(100, "Reading STEP file..."); + pi->Show(); + aReader.Transfer(hDoc); + pi->EndScope(); + } + catch (OSD_Exception) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + Base::Console().Error("%s\n", e->GetMessageString()); + Base::Console().Message("Try to load STEP file without colors...\n"); + + Part::ImportStepParts(pcDoc,Utf8Name.c_str()); + pcDoc->recompute(); + } + } + else if (file.hasExtension("igs") || file.hasExtension("iges")) { + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("IGES"); + + try { + IGESControl_Controller::Init(); + IGESCAFControl_Reader aReader; + // http://www.opencascade.org/org/forum/thread_20603/?forum=3 + aReader.SetReadVisible(hGrp->GetBool("SkipBlankEntities", true) + ? Standard_True : Standard_False); + aReader.SetColorMode(true); + aReader.SetNameMode(true); + aReader.SetLayerMode(true); + if (aReader.ReadFile((const char*)name8bit.c_str()) != IFSelect_RetDone) { + throw Py::Exception(Base::BaseExceptionFreeCADError, "cannot read IGES file"); + } + + Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); + aReader.WS()->MapReader()->SetProgress(pi); + pi->NewScope(100, "Reading IGES file..."); + pi->Show(); + aReader.Transfer(hDoc); + pi->EndScope(); + } + catch (OSD_Exception) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + Base::Console().Error("%s\n", e->GetMessageString()); + Base::Console().Message("Try to load IGES file without colors...\n"); + + Part::ImportIgesParts(pcDoc,Utf8Name.c_str()); + pcDoc->recompute(); + } + } + else { + throw Py::Exception(Base::BaseExceptionFreeCADError, "no supported file format"); } - Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); - aReader.WS()->MapReader()->SetProgress(pi); - pi->NewScope(100, "Reading IGES file..."); - pi->Show(); - aReader.Transfer(hDoc); - pi->EndScope(); + ImportOCAFExt ocaf(hDoc, pcDoc, file.fileNamePure()); + ocaf.loadShapes(); + pcDoc->recompute(); } - else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "no supported file format"); - return 0; + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(Base::BaseExceptionFreeCADError, e->GetMessageString()); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); } - static QPointer dlg = 0; - if (!dlg) { - dlg = new QDialog(Gui::getMainWindow()); - QTreeWidget* tree = new QTreeWidget(); - tree->setHeaderLabel(QString::fromLatin1("OCAF Browser")); - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(tree); - dlg->setLayout(layout); - - QDialogButtonBox* btn = new QDialogButtonBox(dlg); - btn->setStandardButtons(QDialogButtonBox::Close); - QObject::connect(btn, SIGNAL(rejected()), dlg, SLOT(reject())); - QHBoxLayout *boxlayout = new QHBoxLayout; - boxlayout->addWidget(btn); - layout->addLayout(boxlayout); - } - - dlg->setWindowTitle(QString::fromUtf8(file.fileName().c_str())); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->show(); - - OCAFBrowser browse(hDoc); - browse.load(dlg->findChild()); + return Py::None(); } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(Base::BaseExceptionFreeCADError, e->GetMessageString()); - return 0; - } - PY_CATCH + Py::Object exporter(const Py::Tuple& args) + { + PyObject* object; + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "Oet",&object,"utf-8",&Name)) + throw Py::Exception(); - Py_Return; + std::string Utf8Name = std::string(Name); + PyMem_Free(Name); + std::string name8bit = Part::encodeFilename(Utf8Name); + + try { + Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); + Handle(TDocStd_Document) hDoc; + hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); + Import::ExportOCAF ocaf(hDoc); + + 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); + std::vector colors; + Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part); + if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) { + colors = static_cast(vp)->DiffuseColor.getValues(); + if (colors.empty()) + colors.push_back(static_cast(vp)->ShapeColor.getValue()); + } + ocaf.saveShape(part, colors); + } + else { + Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue()); + } + } + } + + Base::FileInfo file(Utf8Name.c_str()); + if (file.hasExtension("stp") || file.hasExtension("step")) { + //Interface_Static::SetCVal("write.step.schema", "AP214IS"); + STEPCAFControl_Writer writer; + writer.Transfer(hDoc, STEPControl_AsIs); + + // edit STEP header +#if OCC_VERSION_HEX >= 0x060500 + APIHeaderSection_MakeHeader makeHeader(writer.ChangeWriter().Model()); +#else + APIHeaderSection_MakeHeader makeHeader(writer.Writer().Model()); +#endif + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("STEP"); + + makeHeader.SetName(new TCollection_HAsciiString((const Standard_CString)(Utf8Name.c_str()))); + makeHeader.SetAuthorValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Author", "Author").c_str())); + makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Company").c_str())); + makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::GetApplication().getExecutableName())); + makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model")); + IFSelect_ReturnStatus ret = writer.Write((const char*)name8bit.c_str()); + if (ret == IFSelect_RetError || ret == IFSelect_RetFail || ret == IFSelect_RetStop) { + PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); + throw Py::Exception(); + } + } + else if (file.hasExtension("igs") || file.hasExtension("iges")) { + IGESControl_Controller::Init(); + IGESCAFControl_Writer writer; + IGESData_GlobalSection header = writer.Model()->GlobalSection(); + header.SetAuthorName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.author"))); + header.SetCompanyName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.company"))); + header.SetSendName(new TCollection_HAsciiString(Interface_Static::CVal("write.iges.header.product"))); + writer.Model()->SetGlobalSection(header); + writer.Transfer(hDoc); + Standard_Boolean ret = writer.Write((const char*)name8bit.c_str()); + if (!ret) { + PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str()); + throw Py::Exception(); + } + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(Base::BaseExceptionFreeCADError, e->GetMessageString()); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + return Py::None(); + } + Py::Object ocaf(const Py::Tuple& args) + { + const char* Name; + if (!PyArg_ParseTuple(args.ptr(), "s",&Name)) + throw Py::Exception(); + + try { + //Base::Console().Log("Insert in Part with %s",Name); + Base::FileInfo file(Name); + + Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication(); + Handle(TDocStd_Document) hDoc; + hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc); + + if (file.hasExtension("stp") || file.hasExtension("step")) { + STEPCAFControl_Reader aReader; + aReader.SetColorMode(true); + aReader.SetNameMode(true); + aReader.SetLayerMode(true); + if (aReader.ReadFile((Standard_CString)Name) != IFSelect_RetDone) { + throw Py::Exception(PyExc_IOError, "cannot read STEP file"); + } + + Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); + aReader.Reader().WS()->MapReader()->SetProgress(pi); + pi->NewScope(100, "Reading STEP file..."); + pi->Show(); + aReader.Transfer(hDoc); + pi->EndScope(); + } + else if (file.hasExtension("igs") || file.hasExtension("iges")) { + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("IGES"); + IGESControl_Controller::Init(); + IGESCAFControl_Reader aReader; + // http://www.opencascade.org/org/forum/thread_20603/?forum=3 + aReader.SetReadVisible(hGrp->GetBool("SkipBlankEntities", true) + ? Standard_True : Standard_False); + aReader.SetColorMode(true); + aReader.SetNameMode(true); + aReader.SetLayerMode(true); + if (aReader.ReadFile((Standard_CString)Name) != IFSelect_RetDone) { + throw Py::Exception(PyExc_IOError, "cannot read IGES file"); + } + + Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100); + aReader.WS()->MapReader()->SetProgress(pi); + pi->NewScope(100, "Reading IGES file..."); + pi->Show(); + aReader.Transfer(hDoc); + pi->EndScope(); + } + else { + throw Py::Exception(Base::BaseExceptionFreeCADError, "no supported file format"); + } + + static QPointer dlg = 0; + if (!dlg) { + dlg = new QDialog(Gui::getMainWindow()); + QTreeWidget* tree = new QTreeWidget(); + tree->setHeaderLabel(QString::fromLatin1("OCAF Browser")); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(tree); + dlg->setLayout(layout); + + QDialogButtonBox* btn = new QDialogButtonBox(dlg); + btn->setStandardButtons(QDialogButtonBox::Close); + QObject::connect(btn, SIGNAL(rejected()), dlg, SLOT(reject())); + QHBoxLayout *boxlayout = new QHBoxLayout; + boxlayout->addWidget(btn); + layout->addLayout(boxlayout); + } + + dlg->setWindowTitle(QString::fromUtf8(file.fileName().c_str())); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->show(); + + OCAFBrowser browse(hDoc); + browse.load(dlg->findChild()); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(Base::BaseExceptionFreeCADError, e->GetMessageString()); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef ImportGui_Import_methods[] = { - {"open" ,open ,METH_VARARGS, - "open(string) -- Open the file and create a new document."}, - {"insert" ,importer ,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."}, - {"ocaf" ,ocaf ,METH_VARARGS, - "ocaf(string) -- Browse the ocaf structure."}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace ImportGui diff --git a/src/Mod/Inspection/App/AppInspection.cpp b/src/Mod/Inspection/App/AppInspection.cpp index b8d5819cd6..4bb9112ca1 100644 --- a/src/Mod/Inspection/App/AppInspection.cpp +++ b/src/Mod/Inspection/App/AppInspection.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) YEAR YOUR NAME * + * Copyright (c) 2004 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * @@ -26,30 +26,45 @@ # include #endif +#include +#include + #include #include "InspectionFeature.h" -/* registration table */ -extern struct PyMethodDef Inspection_methods[]; +namespace Inspection { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("Inspection") + { + initialize("This module is the Inspection module."); // register with Python + } -PyDoc_STRVAR(module_Inspection_doc, -"This module is the Inspection module."); + virtual ~Module() {} + +private: +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace Inspection /* Python entry */ -extern "C" { -void InspectionExport initInspection() { +PyMODINIT_FUNC initInspection() { // ADD YOUR CODE HERE // // - (void) Py_InitModule3("Inspection", Inspection_methods, module_Inspection_doc); /* mod name, table ptr */ + (void)Inspection::initModule(); Base::Console().Log("Loading Inspection module... done\n"); Inspection::PropertyDistanceList ::init(); Inspection::Feature ::init(); Inspection::Group ::init(); } - -} // extern "C" diff --git a/src/Mod/Inspection/App/CMakeLists.txt b/src/Mod/Inspection/App/CMakeLists.txt index f0e7477700..7437050998 100644 --- a/src/Mod/Inspection/App/CMakeLists.txt +++ b/src/Mod/Inspection/App/CMakeLists.txt @@ -27,7 +27,6 @@ set(Inspection_LIBS SET(Inspection_SRCS AppInspection.cpp - AppInspectionPy.cpp InspectionFeature.cpp InspectionFeature.h PreCompiled.cpp diff --git a/src/Mod/Inspection/Gui/AppInspectionGui.cpp b/src/Mod/Inspection/Gui/AppInspectionGui.cpp index a47e74cbbb..e403b7c969 100644 --- a/src/Mod/Inspection/Gui/AppInspectionGui.cpp +++ b/src/Mod/Inspection/Gui/AppInspectionGui.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) YEAR YOUR NAME * + * Copyright (c) 2004 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include @@ -36,16 +39,30 @@ void CreateInspectionCommands(void); -/* registration table */ -extern struct PyMethodDef InspectionGui_methods[]; +namespace InspectionGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("InspectionGui") + { + initialize("This module is the InspectionGui module."); // register with Python + } -PyDoc_STRVAR(module_InspectionGui_doc, -"This module is the InspectionGui module."); + virtual ~Module() {} + +private: +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace InspectionGui /* Python entry */ -extern "C" { -void InspectionGuiExport initInspectionGui() +PyMODINIT_FUNC initInspectionGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -62,8 +79,6 @@ void InspectionGuiExport initInspectionGui() // // - (void) Py_InitModule3("InspectionGui", InspectionGui_methods, module_InspectionGui_doc); /* mod name, table ptr */ + (void)InspectionGui::initModule(); Base::Console().Log("Loading GUI of Inspection module... done\n"); } - -} // extern "C" diff --git a/src/Mod/Inspection/Gui/CMakeLists.txt b/src/Mod/Inspection/Gui/CMakeLists.txt index 86df33cbfb..d2b41a1069 100644 --- a/src/Mod/Inspection/Gui/CMakeLists.txt +++ b/src/Mod/Inspection/Gui/CMakeLists.txt @@ -39,7 +39,6 @@ SET(InspectionGui_SRCS ${Inspection_QRC_SRCS} ${Dialogs_SRCS} AppInspectionGui.cpp - AppInspectionGuiPy.cpp Command.cpp PreCompiled.cpp PreCompiled.h diff --git a/src/Mod/Mesh/App/AppMesh.cpp b/src/Mod/Mesh/App/AppMesh.cpp index c749a3bc8e..742650b73d 100644 --- a/src/Mod/Mesh/App/AppMesh.cpp +++ b/src/Mod/Mesh/App/AppMesh.cpp @@ -44,25 +44,14 @@ #include "FeatureMeshDefects.h" #include "FeatureMeshSolid.h" -/* registration table */ -extern struct PyMethodDef Mesh_Import_methods[]; - - -PyDoc_STRVAR(module_doc, -"The functions in this module allow working with mesh objects.\n" -"A set of functions are provided that allow to read in registered mesh file formats\n" -"to either an newly created or already exising document.\n" -"\n" -"open(string) -- Create a new document and a Mesh::Import feature to load the file into the document.\n" -"insert(string, string) -- Create a Mesh::Import feature to load the file into the given document.\n" -"mesh() -- Create an empty mesh object.\n" -"\n"); +namespace Mesh { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void MeshExport initMesh() +PyMODINIT_FUNC initMesh() { - PyObject* meshModule = Py_InitModule3("Mesh", Mesh_Import_methods, module_doc); /* mod name, table ptr */ + PyObject* meshModule = Mesh::initModule(); Base::Console().Log("Loading Mesh module... done\n"); // NOTE: To finish the initialization of our own type objects we must @@ -111,6 +100,3 @@ void MeshExport initMesh() Mesh::Torus ::init(); Mesh::Cube ::init(); } - - -} // extern "C" diff --git a/src/Mod/Mesh/App/AppMeshPy.cpp b/src/Mod/Mesh/App/AppMeshPy.cpp index d672679c53..6de5151bad 100644 --- a/src/Mod/Mesh/App/AppMeshPy.cpp +++ b/src/Mod/Mesh/App/AppMeshPy.cpp @@ -24,6 +24,9 @@ #ifndef _PreComp_ #endif +#include +#include + #include #include #include @@ -49,39 +52,108 @@ using namespace Mesh; using namespace MeshCore; - -/* module functions */ -static PyObject * read(PyObject *self, PyObject *args) +namespace Mesh { +class Module : public Py::ExtensionModule { - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("Mesh") + { + add_varargs_method("read",&Module::read, + "Read a mesh from a file and returns a Mesh object." + ); + add_varargs_method("open",&Module::open, + "open(string) -- Create a new document and a Mesh::Import feature to load the file into the document." + ); + add_varargs_method("insert",&Module::importer, + "insert(string|mesh,[string]) -- Load or insert a mesh into the given or active document." + ); + add_varargs_method("insert",&Module::importer, + "insert(string|mesh,[string]) -- Load or insert a mesh into the given or active document." + ); + add_varargs_method("export",&Module::exporter, + "export(list,string,[tolerance]) -- Export a list of objects into a single file. tolerance is in mm\n" + "and specifies the maximum acceptable deviation between the specified objects and the exported mesh." + ); + add_varargs_method("show",&Module::show, + "Put a mesh object in the active document or creates one if needed" + ); + add_varargs_method("createBox",&Module::createBox, + "Create a solid mesh box" + ); + add_varargs_method("createPlane",&Module::createPlane, + "Create a mesh XY plane normal +Z" + ); + add_varargs_method("createSphere",&Module::createSphere, + "Create a tessellated sphere" + ); + add_varargs_method("createEllipsoid",&Module::createEllipsoid, + "Create a tessellated ellipsoid" + ); + add_varargs_method("createCylinder",&Module::createCylinder, + "Create a tessellated cylinder" + ); + add_varargs_method("createCone",&Module::createCone, + "Create a tessellated cone" + ); + add_varargs_method("createTorus",&Module::createTorus, + "Create a tessellated torus" + ); + add_varargs_method("calculateEigenTransform",&Module::calculateEigenTransform, + "calculateEigenTransform(seq(Base.Vector)) -- Calculates the eigen Transformation from a list of points.\n" + "calculate the point's local coordinate system with the center\n" + "of gravity as origin. The local coordinate system is computed\n" + "this way that u has minimum and w has maximum expansion.\n" + "The local coordinate system is right-handed.\n" + ); + add_varargs_method("polynomialFit",&Module::polynomialFit, + "polynomialFit(seq(Base.Vector)) -- Calculates a polynomial fit." + ); + initialize("The functions in this module allow working with mesh objects.\n" + "A set of functions are provided that allow to read in registered mesh file formats\n" + "to either an newly created or already exising document.\n" + "\n" + "open(string) -- Create a new document and a Mesh::Import feature to load the file into the document.\n" + "insert(string, string) -- Create a Mesh::Import feature to load the file into the given document.\n" + "Mesh() -- Create an empty mesh object.\n" + "\n"); + } + + 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 Base::Exception &e) { + throw Py::RuntimeError(e.what()); + } + catch (const std::exception &e) { + throw Py::RuntimeError(e.what()); + } + } + 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); - PY_TRY { std::auto_ptr mesh(new MeshObject); - if (mesh->load(EncodedName.c_str())) { - return new MeshPy(mesh.release()); - } - else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Loading of mesh was aborted"); - return NULL; - } - } PY_CATCH; + mesh->load(EncodedName.c_str()); + return Py::asObject(new MeshPy(mesh.release())); + } + Py::Object open(const Py::Tuple& args) + { + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name)) + throw Py::Exception(); - Py_Return; -} + std::string EncodedName = std::string(Name); + PyMem_Free(Name); -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 { MeshObject mesh; MeshCore::Material mat; if (mesh.load(EncodedName.c_str(), &mat)) { @@ -121,21 +193,19 @@ static PyObject * open(PyObject *self, PyObject *args) pcFeature->purgeTouched(); } } - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object importer(const Py::Tuple& args) + { + char* Name; + char* DocName=0; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); -static PyObject * importer(PyObject *self, PyObject *args) -{ - char* Name; - char* DocName=0; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { App::Document *pcDoc = 0; if (DocName) pcDoc = App::GetApplication().getDocument(DocName); @@ -183,24 +253,27 @@ static PyObject * importer(PyObject *self, PyObject *args) pcFeature->purgeTouched(); } } - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object exporter(const Py::Tuple& args) + { + PyObject *object; + char *Name; -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); + // If tolerance is specified via python interface, use that. + // If not, use the preference, if that exists, else default to 0.1mm. + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Mesh"); + float fTolerance = hGrp->GetFloat( "MaxDeviationExport", 0.1f ); - float fTolerance = 0.1f; - MeshObject global_mesh; + if (!PyArg_ParseTuple(args.ptr(), "Oet|f", &object, "utf-8", &Name, &fTolerance)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + MeshObject global_mesh; - PY_TRY { Py::Sequence list(object); Base::Type meshId = Base::Type::fromName("Mesh::Feature"); Base::Type partId = Base::Type::fromName("Part::Feature"); @@ -239,19 +312,15 @@ static PyObject * exporter(PyObject *self, PyObject *args) // export mesh compound global_mesh.save(EncodedName.c_str()); - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object show(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O!", &(MeshPy::Type), &pcObj)) + throw Py::Exception(); -static PyObject * -show(PyObject *self, PyObject *args) -{ - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O!", &(MeshPy::Type), &pcObj)) - return NULL; - - PY_TRY { App::Document *pcDoc = App::GetApplication().getActiveDocument(); if (!pcDoc) pcDoc = App::GetApplication().newDocument(); @@ -259,151 +328,22 @@ show(PyObject *self, PyObject *args) Mesh::Feature *pcFeature = (Mesh::Feature *)pcDoc->addObject("Mesh::Feature", "Mesh"); Mesh::MeshObject* mo = pMesh->getMeshObjectPtr(); if (!mo) { - PyErr_SetString(PyExc_ReferenceError, - "object doesn't reference a valid mesh"); - return 0; + throw Py::Exception(PyExc_ReferenceError, "object doesn't reference a valid mesh"); } // copy the data pcFeature->Mesh.setValue(*mo); - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object createBox(const Py::Tuple& args) + { + float length = 10.0f; + float width = 10.0f; + float height = 10.0f; + float edgelen = -1.0f; + if (!PyArg_ParseTuple(args.ptr(), "|ffff",&length,&width,&height,&edgelen)) + throw Py::Exception(); -static PyObject * -createPlane(PyObject *self, PyObject *args) -{ - float x=1,y=0,z=0; - if (!PyArg_ParseTuple(args, "|fff",&x,&y,&z)) // convert args: Python->C - return NULL; // NULL triggers exception - - if(y==0) - y=x; - - float hx = x/2.0f; - float hy = y/2.0f; - - PY_TRY { - std::vector TriaList; - TriaList.push_back(MeshCore::MeshGeomFacet(Base::Vector3f(-hx, -hy, 0.0),Base::Vector3f(hx, hy, 0.0),Base::Vector3f(-hx, hy, 0.0))); - TriaList.push_back(MeshCore::MeshGeomFacet(Base::Vector3f(-hx, -hy, 0.0),Base::Vector3f(hx, -hy, 0.0),Base::Vector3f(hx, hy, 0.0))); - - std::auto_ptr mesh(new MeshObject); - mesh->addFacets(TriaList); - return new MeshPy(mesh.release()); - } PY_CATCH; -} - -static PyObject * -createSphere(PyObject *self, PyObject *args) -{ - float radius = 5.0f; - int sampling = 50; - if (!PyArg_ParseTuple(args, "|fi",&radius,&sampling)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - MeshObject* mesh = MeshObject::createSphere(radius, sampling); - if (!mesh) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Creation of sphere failed"); - return NULL; - } - return new MeshPy(mesh); - } PY_CATCH; -} - -static PyObject * -createEllipsoid(PyObject *self, PyObject *args) -{ - float radius1 = 2.0f; - float radius2 = 4.0f; - int sampling = 50; - if (!PyArg_ParseTuple(args, "|ffi",&radius1,&radius2,&sampling)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - MeshObject* mesh = MeshObject::createEllipsoid(radius1, radius2, sampling); - if (!mesh) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Creation of ellipsoid failed"); - return NULL; - } - return new MeshPy(mesh); - } PY_CATCH; -} - -static PyObject * -createCylinder(PyObject *self, PyObject *args) -{ - float radius = 2.0f; - float length = 10.0f; - int closed = 1; - float edgelen = 1.0f; - int sampling = 50; - if (!PyArg_ParseTuple(args, "|ffifi",&radius,&length,&closed,&edgelen,&sampling)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - MeshObject* mesh = MeshObject::createCylinder(radius, length, closed, edgelen, sampling); - if (!mesh) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Creation of cylinder failed"); - return NULL; - } - return new MeshPy(mesh); - } PY_CATCH; -} - -static PyObject * -createCone(PyObject *self, PyObject *args) -{ - float radius1 = 2.0f; - float radius2 = 4.0f; - float len = 10.0f; - int closed = 1; - float edgelen = 1.0f; - int sampling = 50; - if (!PyArg_ParseTuple(args, "|fffifi",&radius1,&radius2,&len,&closed,&edgelen,&sampling)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - MeshObject* mesh = MeshObject::createCone(radius1, radius2, len, closed, edgelen, sampling); - if (!mesh) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Creation of cone failed"); - return NULL; - } - return new MeshPy(mesh); - } PY_CATCH; -} - -static PyObject * -createTorus(PyObject *self, PyObject *args) -{ - float radius1 = 10.0f; - float radius2 = 2.0f; - int sampling = 50; - if (!PyArg_ParseTuple(args, "|ffi",&radius1,&radius2,&sampling)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { - MeshObject* mesh = MeshObject::createTorus(radius1, radius2, sampling); - if (!mesh) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Creation of torus failed"); - return NULL; - } - return new MeshPy(mesh); - } PY_CATCH; -} - -static PyObject * -createBox(PyObject *self, PyObject *args) -{ - float length = 10.0f; - float width = 10.0f; - float height = 10.0f; - float edgelen = -1.0f; - if (!PyArg_ParseTuple(args, "|ffff",&length,&width,&height,&edgelen)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { MeshObject* mesh; if (edgelen < 0.0f) mesh = MeshObject::createCube(length, width, height); @@ -411,27 +351,115 @@ createBox(PyObject *self, PyObject *args) mesh = MeshObject::createCube(length, width, height, edgelen); if (!mesh) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Creation of box failed"); - return NULL; + throw Py::Exception(Base::BaseExceptionFreeCADError, "Creation of box failed"); } - return new MeshPy(mesh); - } PY_CATCH; -} - -static PyObject * -calculateEigenTransform(PyObject *self, PyObject *args) -{ - PyObject *input; - - if (!PyArg_ParseTuple(args, "O",&input)) - return NULL; - - if (!PySequence_Check(input)) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Input has to be a sequence of Base.Vector()"); - return NULL; + return Py::asObject(new MeshPy(mesh)); } + Py::Object createPlane(const Py::Tuple& args) + { + float x=1,y=0,z=0; + if (!PyArg_ParseTuple(args.ptr(), "|fff",&x,&y,&z)) + throw Py::Exception(); + + if (y==0) + y=x; + + float hx = x/2.0f; + float hy = y/2.0f; + + std::vector TriaList; + TriaList.push_back(MeshCore::MeshGeomFacet(Base::Vector3f(-hx, -hy, 0.0),Base::Vector3f(hx, hy, 0.0),Base::Vector3f(-hx, hy, 0.0))); + TriaList.push_back(MeshCore::MeshGeomFacet(Base::Vector3f(-hx, -hy, 0.0),Base::Vector3f(hx, -hy, 0.0),Base::Vector3f(hx, hy, 0.0))); + + std::auto_ptr mesh(new MeshObject); + mesh->addFacets(TriaList); + return Py::asObject(new MeshPy(mesh.release())); + } + Py::Object createSphere(const Py::Tuple& args) + { + float radius = 5.0f; + int sampling = 50; + if (!PyArg_ParseTuple(args.ptr(), "|fi",&radius,&sampling)) + throw Py::Exception(); + + MeshObject* mesh = MeshObject::createSphere(radius, sampling); + if (!mesh) { + throw Py::Exception(Base::BaseExceptionFreeCADError, "Creation of sphere failed"); + } + return Py::asObject(new MeshPy(mesh)); + } + Py::Object createEllipsoid(const Py::Tuple& args) + { + float radius1 = 2.0f; + float radius2 = 4.0f; + int sampling = 50; + if (!PyArg_ParseTuple(args.ptr(), "|ffi",&radius1,&radius2,&sampling)) + throw Py::Exception(); + + MeshObject* mesh = MeshObject::createEllipsoid(radius1, radius2, sampling); + if (!mesh) { + throw Py::Exception(Base::BaseExceptionFreeCADError, "Creation of ellipsoid failed"); + } + return Py::asObject(new MeshPy(mesh)); + } + Py::Object createCylinder(const Py::Tuple& args) + { + float radius = 2.0f; + float length = 10.0f; + int closed = 1; + float edgelen = 1.0f; + int sampling = 50; + if (!PyArg_ParseTuple(args.ptr(), "|ffifi",&radius,&length,&closed,&edgelen,&sampling)) + throw Py::Exception(); + + MeshObject* mesh = MeshObject::createCylinder(radius, length, closed, edgelen, sampling); + if (!mesh) { + throw Py::Exception(Base::BaseExceptionFreeCADError, "Creation of cylinder failed"); + } + return Py::asObject(new MeshPy(mesh)); + } + Py::Object createCone(const Py::Tuple& args) + { + float radius1 = 2.0f; + float radius2 = 4.0f; + float len = 10.0f; + int closed = 1; + float edgelen = 1.0f; + int sampling = 50; + if (!PyArg_ParseTuple(args.ptr(), "|fffifi",&radius1,&radius2,&len,&closed,&edgelen,&sampling)) + throw Py::Exception(); + + MeshObject* mesh = MeshObject::createCone(radius1, radius2, len, closed, edgelen, sampling); + if (!mesh) { + throw Py::Exception(Base::BaseExceptionFreeCADError, "Creation of cone failed"); + } + return Py::asObject(new MeshPy(mesh)); + } + Py::Object createTorus(const Py::Tuple& args) + { + float radius1 = 10.0f; + float radius2 = 2.0f; + int sampling = 50; + if (!PyArg_ParseTuple(args.ptr(), "|ffi",&radius1,&radius2,&sampling)) + throw Py::Exception(); + + MeshObject* mesh = MeshObject::createTorus(radius1, radius2, sampling); + if (!mesh) { + throw Py::Exception(Base::BaseExceptionFreeCADError, "Creation of torus failed"); + } + return Py::asObject(new MeshPy(mesh)); + } + Py::Object calculateEigenTransform(const Py::Tuple& args) + { + PyObject *input; + + if (!PyArg_ParseTuple(args.ptr(), "O",&input)) + throw Py::Exception(); + + if (!PySequence_Check(input)) { + throw Py::TypeError("Input has to be a sequence of Base.Vector()"); + } - PY_TRY { MeshCore::MeshKernel aMesh; MeshCore::MeshPointArray vertices; vertices.clear(); @@ -461,27 +489,19 @@ calculateEigenTransform(PyObject *self, PyObject *args) pca.Evaluate(); Base::Matrix4D Trafo = pca.Transform(); - return new Base::PlacementPy(new Base::Placement(Trafo) ); - - } PY_CATCH; - - Py_Return; -} - -static PyObject * -polynomialFit(PyObject *self, PyObject *args) -{ - PyObject *input; - - if (!PyArg_ParseTuple(args, "O",&input)) - return NULL; - - if (!PySequence_Check(input)) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Input has to be a sequence of Base.Vector()"); - return NULL; + return Py::asObject(new Base::PlacementPy(new Base::Placement(Trafo))); } + Py::Object polynomialFit(const Py::Tuple& args) + { + PyObject *input; + + if (!PyArg_ParseTuple(args.ptr(), "O",&input)) + throw Py::Exception(); + + if (!PySequence_Check(input)) { + throw Py::TypeError("Input has to be a sequence of Base.Vector()"); + } - PY_TRY { MeshCore::SurfaceFit polyFit; Base::Vector3f point; @@ -523,48 +543,13 @@ polynomialFit(PyObject *self, PyObject *args) } dict.setItem(Py::String("Residuals"), r); - return Py::new_reference_to(dict); - } PY_CATCH; + return dict; + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } - -PyDoc_STRVAR(open_doc, -"open(string) -- Create a new document and a Mesh::Import feature to load the file into the document."); - -PyDoc_STRVAR(inst_doc, -"insert(string|mesh,[string]) -- Load or insert a mesh into the given or active document."); - -PyDoc_STRVAR(export_doc, -"export(list,string) -- Export a list of objects into a single file."); - -PyDoc_STRVAR(calculateEigenTransform_doc, -"calculateEigenTransform(seq(Base.Vector)) -- Calculates the eigen Transformation from a list of points.\n" -"calculate the point's local coordinate system with the center\n" -"of gravity as origin. The local coordinate system is computed\n" -"this way that u has minimum and w has maximum expansion.\n" -"The local coordinate system is right-handed.\n" -); - -PyDoc_STRVAR(polynomialFit_doc, -"polynomialFit(seq(Base.Vector)) -- Calculates a polynomial fit.\n" -); - -/* List of functions defined in the module */ - -struct PyMethodDef Mesh_Import_methods[] = { - {"open" ,open , METH_VARARGS, open_doc}, - {"insert" ,importer, METH_VARARGS, inst_doc}, - {"export" ,exporter, METH_VARARGS, export_doc}, - {"read" ,read, Py_NEWARGS, "Read a mesh from a file and returns a Mesh object."}, - {"show" ,show, Py_NEWARGS, "Put a mesh object in the active document or creates one if needed"}, - {"createBox" ,createBox, Py_NEWARGS, "Create a solid mesh box"}, - {"createPlane",createPlane, Py_NEWARGS, "Create a mesh XY plane normal +Z"}, - {"createSphere",createSphere, Py_NEWARGS, "Create a tessellated sphere"}, - {"createEllipsoid",createEllipsoid, Py_NEWARGS, "Create a tessellated ellipsoid"}, - {"createCylinder",createCylinder, Py_NEWARGS, "Create a tessellated cylinder"}, - {"createCone",createCone, Py_NEWARGS, "Create a tessellated cone"}, - {"createTorus",createTorus, Py_NEWARGS, "Create a tessellated torus"}, - {"calculateEigenTransform",calculateEigenTransform, METH_VARARGS, calculateEigenTransform_doc}, - {"polynomialFit",polynomialFit, METH_VARARGS, polynomialFit_doc}, - {NULL, NULL} /* sentinel */ -}; +} // namespace Mesh diff --git a/src/Mod/Mesh/App/MeshProperties.cpp b/src/Mod/Mesh/App/MeshProperties.cpp index 7c3425834d..38258bc2a8 100644 --- a/src/Mod/Mesh/App/MeshProperties.cpp +++ b/src/Mod/Mesh/App/MeshProperties.cpp @@ -192,7 +192,7 @@ unsigned int PropertyNormalList::getMemSize (void) const return static_cast(_lValueList.size() * sizeof(Base::Vector3f)); } -void PropertyNormalList::transform(const Base::Matrix4D &mat) +void PropertyNormalList::transformGeometry(const Base::Matrix4D &mat) { // A normal vector is only a direction with unit length, so we only need to rotate it // (no translations or scaling) @@ -222,7 +222,6 @@ void PropertyNormalList::transform(const Base::Matrix4D &mat) } hasSetValue(); - } // ---------------------------------------------------------------------------- @@ -300,7 +299,7 @@ std::vector PropertyCurvatureList::getCurvature( int mode ) const return fValues; } -void PropertyCurvatureList::transform(const Base::Matrix4D &mat) +void PropertyCurvatureList::transformGeometry(const Base::Matrix4D &mat) { // The principal direction is only a vector with unit length, so we only need to rotate it // (no translations or scaling) diff --git a/src/Mod/Mesh/App/MeshProperties.h b/src/Mod/Mesh/App/MeshProperties.h index 94efa57868..567eecde71 100644 --- a/src/Mod/Mesh/App/MeshProperties.h +++ b/src/Mod/Mesh/App/MeshProperties.h @@ -65,11 +65,11 @@ public: void setValue(float x, float y, float z); const Base::Vector3f& operator[] (const int idx) const { - return _lValueList.operator[] (idx); + return _lValueList[idx]; } void set1Value (const int idx, const Base::Vector3f& value) { - _lValueList.operator[] (idx) = value; + _lValueList[idx] = value; } void setValues (const std::vector& values); @@ -92,7 +92,7 @@ public: virtual unsigned int getMemSize (void) const; - void transform(const Base::Matrix4D &rclMat); + void transformGeometry(const Base::Matrix4D &rclMat); private: std::vector _lValueList; @@ -132,10 +132,16 @@ public: void setValues(const std::vector&); /// index operator - const CurvatureInfo& operator[] (const int idx) const {return _lValueList.operator[] (idx);} - void set1Value (const int idx, const CurvatureInfo& value){_lValueList.operator[] (idx) = value;} - const std::vector &getValues(void) const{return _lValueList;} - void transform(const Base::Matrix4D &rclMat); + const CurvatureInfo& operator[] (const int idx) const { + return _lValueList[idx]; + } + void set1Value (const int idx, const CurvatureInfo& value) { + _lValueList[idx] = value; + } + const std::vector &getValues(void) const { + return _lValueList; + } + void transformGeometry(const Base::Matrix4D &rclMat); void Save (Base::Writer &writer) const; void Restore(Base::XMLReader &reader); @@ -231,7 +237,9 @@ public: void setPyObject(PyObject *value); //@} - const char* getEditorName(void) const { return "MeshGui::PropertyMeshKernelItem"; } + const char* getEditorName(void) const { + return "MeshGui::PropertyMeshKernelItem"; + } /** @name Save/restore */ //@{ diff --git a/src/Mod/Mesh/Gui/AppMeshGui.cpp b/src/Mod/Mesh/Gui/AppMeshGui.cpp index 37a0ec4904..ad69792ca8 100644 --- a/src/Mod/Mesh/Gui/AppMeshGui.cpp +++ b/src/Mod/Mesh/Gui/AppMeshGui.cpp @@ -28,6 +28,9 @@ #include #include +#include +#include + #include #include #include @@ -39,6 +42,7 @@ #include "DlgEvaluateMeshImp.h" #include "PropertyEditorMesh.h" #include "DlgSettingsMeshView.h" +#include "DlgSettingsImportExportImp.h" #include "SoFCMeshObject.h" #include "SoFCIndexedFaceSet.h" #include "SoPolygon.h" @@ -62,14 +66,29 @@ void loadMeshResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -static struct PyMethodDef MeshGui_methods[] = { - {NULL, NULL} /* end of table marker */ +namespace MeshGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("MeshGui") + { + initialize("This module is the MeshGui module."); // register with Python + } + + virtual ~Module() {} + +private: }; +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace MeshGui + /* Python entry */ -extern "C" { -void MeshGuiExport initMeshGui() +PyMODINIT_FUNC initMeshGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -84,7 +103,7 @@ void MeshGuiExport initMeshGui() PyErr_SetString(PyExc_ImportError, e.what()); return; } - (void) Py_InitModule("MeshGui", MeshGui_methods); /* mod name, table ptr */ + (void) MeshGui::initModule(); Base::Console().Log("Loading GUI of Mesh module... done\n"); // Register icons @@ -96,6 +115,7 @@ void MeshGuiExport initMeshGui() // register preferences pages (void)new Gui::PrefPageProducer ("Display"); + (void)new Gui::PrefPageProducer ( QT_TRANSLATE_NOOP("QObject", "Import-Export") ); MeshGui::SoFCMeshObjectElement ::initClass(); MeshGui::SoSFMeshObject ::initClass(); @@ -135,5 +155,3 @@ void MeshGuiExport initMeshGui() // add resources and reloads the translators loadMeshResource(); } - -} // extern "C" { diff --git a/src/Mod/Mesh/Gui/CMakeLists.txt b/src/Mod/Mesh/Gui/CMakeLists.txt index 0a9ac83869..37df2ad5d3 100644 --- a/src/Mod/Mesh/Gui/CMakeLists.txt +++ b/src/Mod/Mesh/Gui/CMakeLists.txt @@ -19,6 +19,8 @@ set(Mesh_MOC_HDRS DlgEvaluateMeshImp.h DlgRegularSolidImp.h DlgSettingsMeshView.h + DlgSettingsImportExportImp.h + DlgSmoothing.h MeshEditor.h PropertyEditorMesh.h @@ -32,6 +34,7 @@ set(Dialogs_UIC_SRCS DlgEvaluateMesh.ui DlgRegularSolid.ui DlgSettingsMeshView.ui + DlgSettingsImportExport.ui DlgSmoothing.ui RemoveComponents.ui Segmentation.ui @@ -49,6 +52,8 @@ SET(Dialogs_SRCS DlgSettingsMeshView.ui DlgSettingsMeshView.cpp DlgSettingsMeshView.h + DlgSettingsImportExportImp.cpp + DlgSettingsImportExportImp.h DlgSmoothing.ui DlgSmoothing.cpp DlgSmoothing.h diff --git a/src/Mod/Mesh/Gui/DlgSettingsImportExport.ui b/src/Mod/Mesh/Gui/DlgSettingsImportExport.ui new file mode 100644 index 0000000000..fe28839118 --- /dev/null +++ b/src/Mod/Mesh/Gui/DlgSettingsImportExport.ui @@ -0,0 +1,96 @@ + + + MeshGui::DlgSettingsImportExport + + + + 0 + 0 + 539 + 339 + + + + Mesh Formats + + + + + + Qt::Vertical + + + + 20 + 61 + + + + + + + + Export + + + + + + + + Defines the deviation of tessellation to the actual surface + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; font-size:7.8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Tessellation</span></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"><span style=" font-weight:400;">Defines the maximum deviation of the tessellated mesh to the surface. The smaller the value is the slower the render speed and the nicer the appearance are.</span></p></body></html> + + + Maximum mesh deviation + + + + + + + mm + + + 4 + + + 0.000000000000000 + + + 100000000.000000000000000 + + + 0.010000000000000 + + + 0.100000000000000 + + + MaxDeviationExport + + + Mod/Mesh + + + + + + + + + + + + + + Gui::PrefDoubleSpinBox + QDoubleSpinBox +
Gui/PrefWidgets.h
+
+
+ + +
diff --git a/src/Mod/Inspection/Gui/AppInspectionGuiPy.cpp b/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.cpp similarity index 62% rename from src/Mod/Inspection/Gui/AppInspectionGuiPy.cpp rename to src/Mod/Mesh/Gui/DlgSettingsImportExportImp.cpp index b7913e9c47..77cae3897d 100644 --- a/src/Mod/Inspection/Gui/AppInspectionGuiPy.cpp +++ b/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.cpp @@ -1,35 +1,65 @@ -/*************************************************************************** - * Copyright (c) YEAR YOUR NAME * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -#endif - - -#include -#include - -/* registration table */ -struct PyMethodDef InspectionGui_methods[] = { - {NULL, NULL} /* end of table marker */ -}; +/*************************************************************************** + * Copyright (c) 2016 Ian Rees * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#include "DlgSettingsImportExportImp.h" +#include "ui_DlgSettingsImportExport.h" + +using namespace MeshGui; + +DlgSettingsImportExport::DlgSettingsImportExport(QWidget* parent) + : PreferencePage(parent), ui(new Ui_DlgSettingsImportExport) +{ + ui->setupUi(this); +} + +DlgSettingsImportExport::~DlgSettingsImportExport() +{ + // no need to delete child widgets, Qt does it all for us +} + +void DlgSettingsImportExport::saveSettings() +{ + ui->maxDeviationExport->onSave(); +} + +void DlgSettingsImportExport::loadSettings() +{ + ui->maxDeviationExport->onRestore(); +} + +/** + * Sets the strings of the subwidgets using the current language. + */ +void DlgSettingsImportExport::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + } + else { + QWidget::changeEvent(e); + } +} + +#include "moc_DlgSettingsImportExportImp.cpp" + diff --git a/src/Mod/Inspection/App/AppInspectionPy.cpp b/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.h similarity index 65% rename from src/Mod/Inspection/App/AppInspectionPy.cpp rename to src/Mod/Mesh/Gui/DlgSettingsImportExportImp.h index 88f94e67d0..b2a9877c6c 100644 --- a/src/Mod/Inspection/App/AppInspectionPy.cpp +++ b/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.h @@ -1,38 +1,56 @@ -/*************************************************************************** - * Copyright (c) YEAR YOUR NAME * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -#endif - -#include - -#include -#include -#include - - -/* registration table */ -struct PyMethodDef Inspection_methods[] = { - {NULL, NULL} /* end of table marker */ -}; +/*************************************************************************** + * Copyright (c) 2016 Ian Rees * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef MESHGUI_DLGSETTINGSIMPORTEXPORTIMP_H +#define MESHGUI_DLGSETTINGSIMPORTEXPORTIMP_H + +#include + +namespace MeshGui { + +class Ui_DlgSettingsImportExport; +/** + * The DlgSettingsImportExportImp class implements a preference page to change settings + * for Importing and Exporting mesh objects. + */ +class DlgSettingsImportExport : public Gui::Dialog::PreferencePage +{ + Q_OBJECT + +public: + DlgSettingsImportExport(QWidget* parent = 0); + ~DlgSettingsImportExport(); + +protected: + void saveSettings(); + void loadSettings(); + void changeEvent(QEvent *e); + +private: + Ui_DlgSettingsImportExport* ui; +}; // end class DlgSettingsImportExport + +} // namespace MeshGui + +#endif // MESHGUI_DLGSETTINGSIMPORTEXPORTIMP_H + diff --git a/src/Mod/MeshPart/App/AppMeshPart.cpp b/src/Mod/MeshPart/App/AppMeshPart.cpp index bf505f9d69..c3ae9c3ff9 100644 --- a/src/Mod/MeshPart/App/AppMeshPart.cpp +++ b/src/Mod/MeshPart/App/AppMeshPart.cpp @@ -30,15 +30,12 @@ #include -extern struct PyMethodDef MeshPart_methods[]; - -PyDoc_STRVAR(module_MeshPart_doc, -"This module is the MeshPart module."); - +namespace MeshPart { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void MeshPartExport initMeshPart() +PyMODINIT_FUNC initMeshPart() { // load dependent module try { @@ -49,15 +46,6 @@ void MeshPartExport initMeshPart() PyErr_SetString(PyExc_ImportError, e.what()); return; } - Py_InitModule3("MeshPart", MeshPart_methods, module_MeshPart_doc); /* mod name, table ptr */ + (void)MeshPart::initModule(); Base::Console().Log("Loading MeshPart module... done\n"); - - - // NOTE: To finish the initialization of our own type objects we must - // call PyType_Ready, otherwise we run into a segmentation fault, later on. - // This function is responsible for adding inherited slots from a type's base class. - - //MeshPart::FeatureViewPart ::init(); } - -} // extern "C" diff --git a/src/Mod/MeshPart/App/AppMeshPartPy.cpp b/src/Mod/MeshPart/App/AppMeshPartPy.cpp index 3395884a79..30c6016594 100644 --- a/src/Mod/MeshPart/App/AppMeshPartPy.cpp +++ b/src/Mod/MeshPart/App/AppMeshPartPy.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -38,82 +41,125 @@ #include "MeshAlgos.h" #include "Mesher.h" -static PyObject * -loftOnCurve(PyObject *self, PyObject *args) +namespace MeshPart { +class Module : public Py::ExtensionModule { - Part::TopoShapePy *pcObject; - PyObject *pcTopoObj,*pcListObj; - float x=0.0f,y=0.0f,z=1.0f,size = 0.1f; - - if (!PyArg_ParseTuple(args, "O!O(fff)f", &(Part::TopoShapePy::Type), &pcTopoObj,&pcListObj,&x,&y,&z,&size)) // convert args: Python->C -// if (!PyArg_ParseTuple(args, "O!O!", &(App::TopoShapePy::Type), &pcTopoObj,&PyList_Type,&pcListObj,x,y,z,size)) // convert args: Python->C - return NULL; // NULL triggers exception - - pcObject = (Part::TopoShapePy*)pcTopoObj; - MeshCore::MeshKernel M; - - std::vector poly; - - if (!PyList_Check(pcListObj)) - Py_Error(Base::BaseExceptionFreeCADError,"List of Tuble of three or two floats needed as second parameter!"); - - int nSize = PyList_Size(pcListObj); - for (int i=0; i("MeshPart") { - PyObject* item = PyList_GetItem(pcListObj, i); - if (!PyTuple_Check(item)) - Py_Error(Base::BaseExceptionFreeCADError,"List of Tuble of three or two floats needed as second parameter!"); - int nTSize = PyTuple_Size(item); - if(nTSize != 2 && nTSize != 3) - Py_Error(Base::BaseExceptionFreeCADError,"List of Tuble of three or two floats needed as second parameter!"); - - Base::Vector3f vec(0,0,0); - - for(int l = 0; l < nTSize;l++) - { - PyObject* item2 = PyTuple_GetItem(item, l); - if (!PyFloat_Check(item2)) - Py_Error(Base::BaseExceptionFreeCADError,"List of Tuble of three or two floats needed as second parameter!"); - vec[l] = (float)PyFloat_AS_DOUBLE(item2); - } - poly.push_back(vec); + add_varargs_method("loftOnCurve",&Module::loftOnCurve, + "Loft on curve." + ); + add_varargs_method("wireFromSegment",&Module::wireFromSegment, + "Create wire(s) from boundary of segment" + ); + add_keyword_method("meshFromShape",&Module::meshFromShape, + "Create mesh from shape" + ); + initialize("This module is the MeshPart module."); // 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(Base::BaseExceptionFreeCADError, 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 loftOnCurve(const Py::Tuple& args) + { + Part::TopoShapePy *pcObject; + PyObject *pcTopoObj,*pcListObj; + float x=0.0f,y=0.0f,z=1.0f,size = 0.1f; + + if (!PyArg_ParseTuple(args.ptr(), "O!O(fff)f", &(Part::TopoShapePy::Type), &pcTopoObj,&pcListObj,&x,&y,&z,&size)) +// if (!PyArg_ParseTuple(args, "O!O!", &(App::TopoShapePy::Type), &pcTopoObj,&PyList_Type,&pcListObj,x,y,z,size)) + throw Py::Exception(); + + pcObject = static_cast(pcTopoObj); + MeshCore::MeshKernel M; + + std::vector poly; + + if (!PyList_Check(pcListObj)) + throw Py::Exception(Base::BaseExceptionFreeCADError,"List of Tuble of three or two floats needed as second parameter!"); + + int nSize = PyList_Size(pcListObj); + for (int i=0; igetTopoShapePtr()->_Shape; // use the MeshAlgos MeshPart::MeshAlgos::LoftOnCurve(M,aShape,poly,Base::Vector3f(x,y,z),size); - - } PY_CATCH; - - return new Mesh::MeshPy(new Mesh::MeshObject(M)); -} - -PyDoc_STRVAR(loft_doc, -"Loft on curve."); - -static PyObject * -wireFromSegment(PyObject *self, PyObject *args) -{ - PyObject *o, *m; - if (!PyArg_ParseTuple(args, "O!O!", &(Mesh::MeshPy::Type), &m,&PyList_Type,&o)) - return 0; - Py::List list(o); - Mesh::MeshObject* mesh = static_cast(m)->getMeshObjectPtr(); - std::vector segm; - segm.reserve(list.size()); - for (unsigned int i=0; i > bounds; - MeshCore::MeshAlgorithm algo(mesh->getKernel()); - algo.GetFacetBorders(segm, bounds); + Py::List list(o); + Mesh::MeshObject* mesh = static_cast(m)->getMeshObjectPtr(); + std::vector segm; + segm.reserve(list.size()); + for (unsigned int i=0; i >::iterator bt; + std::list > bounds; + MeshCore::MeshAlgorithm algo(mesh->getKernel()); + algo.GetFacetBorders(segm, bounds); + + Py::List wires; + std::list >::iterator bt; - try { for (bt = bounds.begin(); bt != bounds.end(); ++bt) { BRepBuilderAPI_MakePolygon mkPoly; for (std::vector::reverse_iterator it = bt->rbegin(); it != bt->rend(); ++it) { @@ -124,87 +170,78 @@ wireFromSegment(PyObject *self, PyObject *args) wires.append(Py::Object(wire, true)); } } - } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(Base::BaseExceptionFreeCADError, e->GetMessageString()); - return 0; - } - return Py::new_reference_to(wires); -} - -static PyObject * -meshFromShape(PyObject *self, PyObject *args, PyObject* kwds) -{ - try { + return wires; + } + Py::Object meshFromShape(const Py::Tuple& args, const Py::Dict& kwds) + { PyObject *shape; static char* kwds_maxLength[] = {"Shape", "MaxLength",NULL}; PyErr_Clear(); double maxLength=0; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_maxLength, + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!d", kwds_maxLength, &(Part::TopoShapePy::Type), &shape, &maxLength)) { MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->_Shape); mesher.setMethod(MeshPart::Mesher::Mefisto); mesher.setMaxLength(maxLength); mesher.setRegular(true); - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } static char* kwds_maxArea[] = {"Shape", "MaxArea",NULL}; PyErr_Clear(); double maxArea=0; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_maxArea, + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!d", kwds_maxArea, &(Part::TopoShapePy::Type), &shape, &maxArea)) { MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->_Shape); mesher.setMethod(MeshPart::Mesher::Mefisto); mesher.setMaxArea(maxArea); mesher.setRegular(true); - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } static char* kwds_localLen[] = {"Shape", "LocalLength",NULL}; PyErr_Clear(); double localLen=0; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_localLen, + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!d", kwds_localLen, &(Part::TopoShapePy::Type), &shape, &localLen)) { MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->_Shape); mesher.setMethod(MeshPart::Mesher::Mefisto); mesher.setLocalLength(localLen); mesher.setRegular(true); - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } static char* kwds_deflection[] = {"Shape", "Deflection",NULL}; PyErr_Clear(); double deflection=0; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O!d", kwds_deflection, + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!d", kwds_deflection, &(Part::TopoShapePy::Type), &shape, &deflection)) { MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->_Shape); mesher.setMethod(MeshPart::Mesher::Mefisto); mesher.setDeflection(deflection); mesher.setRegular(true); - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } static char* kwds_minmaxLen[] = {"Shape", "MinLength","MaxLength",NULL}; PyErr_Clear(); double minLen=0, maxLen=0; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O!dd", kwds_minmaxLen, + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!dd", kwds_minmaxLen, &(Part::TopoShapePy::Type), &shape, &minLen, &maxLen)) { MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->_Shape); mesher.setMethod(MeshPart::Mesher::Mefisto); mesher.setMinMaxLengths(minLen, maxLen); mesher.setRegular(true); - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } #if defined (HAVE_NETGEN) static char* kwds_fineness[] = {"Shape", "Fineness", "SecondOrder", "Optimize", "AllowQuad",NULL}; PyErr_Clear(); int fineness=0, secondOrder=0, optimize=1, allowquad=0; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O!i|iii", kwds_fineness, + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!i|iii", kwds_fineness, &(Part::TopoShapePy::Type), &shape, &fineness, &secondOrder, &optimize, &allowquad)) { MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->_Shape); @@ -213,13 +250,13 @@ meshFromShape(PyObject *self, PyObject *args, PyObject* kwds) mesher.setSecondOrder(secondOrder > 0); mesher.setOptimize(optimize > 0); mesher.setQuadAllowed(allowquad > 0); - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } static char* kwds_user[] = {"Shape", "GrowthRate", "SegPerEdge", "SegPerRadius", "SecondOrder", "Optimize", "AllowQuad",NULL}; PyErr_Clear(); double growthRate=0, nbSegPerEdge=0, nbSegPerRadius=0; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O!|dddiii", kwds_user, + if (PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!|dddiii", kwds_user, &(Part::TopoShapePy::Type), &shape, &growthRate, &nbSegPerEdge, &nbSegPerRadius, &secondOrder, &optimize, &allowquad)) { @@ -231,12 +268,12 @@ meshFromShape(PyObject *self, PyObject *args, PyObject* kwds) mesher.setSecondOrder(secondOrder > 0); mesher.setOptimize(optimize > 0); mesher.setQuadAllowed(allowquad > 0); - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } #endif PyErr_Clear(); - if (PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &shape)) { + if (PyArg_ParseTuple(args.ptr(), "O!", &(Part::TopoShapePy::Type), &shape)) { MeshPart::Mesher mesher(static_cast(shape)->getTopoShapePtr()->_Shape); #if defined (HAVE_NETGEN) mesher.setMethod(MeshPart::Mesher::Netgen); @@ -244,24 +281,16 @@ meshFromShape(PyObject *self, PyObject *args, PyObject* kwds) mesher.setMethod(MeshPart::Mesher::Mefisto); mesher.setRegular(true); #endif - return new Mesh::MeshPy(mesher.createMesh()); + return Py::asObject(new Mesh::MeshPy(mesher.createMesh())); } - } - catch (const Base::Exception& e) { - PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); - return 0; - } - PyErr_SetString(Base::BaseExceptionFreeCADError,"Wrong arguments"); - return 0; + throw Py::Exception(Base::BaseExceptionFreeCADError,"Wrong arguments"); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef MeshPart_methods[] = { - {"loftOnCurve",loftOnCurve, METH_VARARGS, loft_doc}, - {"wireFromSegment",wireFromSegment, METH_VARARGS, - "Create wire(s) from boundary of segment"}, - {"meshFromShape",(PyCFunction)meshFromShape, METH_VARARGS|METH_KEYWORDS, - "Create mesh from shape"}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace MeshPart diff --git a/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp b/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp index 62cca702a1..5af3c42ab0 100644 --- a/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp +++ b/src/Mod/MeshPart/Gui/AppMeshPartGui.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -41,20 +44,37 @@ void loadMeshPartResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef MeshPartGui_Import_methods[]; +namespace MeshPartGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("MeshPartGui") + { + initialize("This module is the MeshPartGui module."); // register with Python + } + + virtual ~Module() {} + +private: +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace MeshPartGui /* Python entry */ -extern "C" { -void MeshPartGuiExport initMeshPartGui() +PyMODINIT_FUNC initMeshPartGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); return; } - (void) Py_InitModule("MeshPartGui", MeshPartGui_Import_methods); /* mod name, table ptr */ + (void)MeshPartGui::initModule(); Base::Console().Log("Loading GUI of MeshPart module... done\n"); // instantiating the commands @@ -64,5 +84,3 @@ void MeshPartGuiExport initMeshPartGui() // add resources and reloads the translators loadMeshPartResource(); } - -} // extern "C" { diff --git a/src/Mod/MeshPart/Gui/AppMeshPartGuiPy.cpp b/src/Mod/MeshPart/Gui/AppMeshPartGuiPy.cpp deleted file mode 100644 index 034c13a5bc..0000000000 --- a/src/Mod/MeshPart/Gui/AppMeshPartGuiPy.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2008 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -#endif - - -/* registration table */ -struct PyMethodDef MeshPartGui_Import_methods[] = { - {NULL, NULL} /* end of table marker */ -}; diff --git a/src/Mod/MeshPart/Gui/CMakeLists.txt b/src/Mod/MeshPart/Gui/CMakeLists.txt index 77b4e8970a..8b49d9725a 100644 --- a/src/Mod/MeshPart/Gui/CMakeLists.txt +++ b/src/Mod/MeshPart/Gui/CMakeLists.txt @@ -48,7 +48,6 @@ SET(MeshPartGui_SRCS ${MeshPartGui_QRC_SRCS} ${MeshPartGui_UIC_HDRS} AppMeshPartGui.cpp - AppMeshPartGuiPy.cpp Command.cpp Resources/MeshPart.qrc PreCompiled.cpp diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 736c2bba6f..2e36616772 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,41 +123,42 @@ 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"); + + // Python exceptions + // PyObject* OCCError = 0; - if (PyObject_IsSubclass(Base::BaseExceptionFreeCADError, - PyExc_RuntimeError)) { - OCCError = PyErr_NewException("Part.OCCError", - Base::BaseExceptionFreeCADError, NULL); + if (PyObject_IsSubclass(Base::BaseExceptionFreeCADError, PyExc_RuntimeError)) { + OCCError = PyErr_NewException("Part.OCCError", Base::BaseExceptionFreeCADError, NULL); } else { Base::Console().Error("Can not inherit Part.OCCError form BaseFreeCADError.\n"); - OCCError = PyErr_NewException("Part.OCCError", - PyExc_RuntimeError, NULL); + OCCError = PyErr_NewException("Part.OCCError", PyExc_RuntimeError, NULL); } Py_INCREF(OCCError); PyModule_AddObject(partModule, "OCCError", OCCError); PartExceptionOCCError = OCCError; //set global variable ;( - PartExceptionOCCDomainError = PyErr_NewException("Part.OCCDomainError", - PartExceptionOCCError, NULL); + + // domain error + PartExceptionOCCDomainError = PyErr_NewException("Part.OCCDomainError", PartExceptionOCCError, NULL); Py_INCREF(PartExceptionOCCDomainError); - PyModule_AddObject(partModule, "OCCDomainError", - PartExceptionOCCDomainError); - PartExceptionOCCRangeError = PyErr_NewException("Part.OCCRangeError", - PartExceptionOCCDomainError, NULL); + PyModule_AddObject(partModule, "OCCDomainError", PartExceptionOCCDomainError); + + // range error + PartExceptionOCCRangeError = PyErr_NewException("Part.OCCRangeError", PartExceptionOCCDomainError, NULL); Py_INCREF(PartExceptionOCCRangeError); PyModule_AddObject(partModule, "OCCRangeError", PartExceptionOCCRangeError); - PartExceptionOCCConstructionError = PyErr_NewException( - "Part.OCCConstructionError", PartExceptionOCCDomainError, NULL); + + // construction error + PartExceptionOCCConstructionError = PyErr_NewException("Part.OCCConstructionError", PartExceptionOCCDomainError, NULL); Py_INCREF(PartExceptionOCCConstructionError); - PyModule_AddObject(partModule, "OCCConstructionError", - PartExceptionOCCConstructionError); - PartExceptionOCCDimensionError = PyErr_NewException( - "Part.OCCDimensionError", PartExceptionOCCDomainError, NULL); + PyModule_AddObject(partModule, "OCCConstructionError", PartExceptionOCCConstructionError); + + // dimension error + PartExceptionOCCDimensionError = PyErr_NewException("Part.OCCDimensionError", PartExceptionOCCDomainError, NULL); Py_INCREF(PartExceptionOCCConstructionError); - PyModule_AddObject(partModule, "OCCDimensionError", - PartExceptionOCCDimensionError); + PyModule_AddObject(partModule, "OCCDimensionError", PartExceptionOCCDimensionError); //rename the types properly to pickle and unpickle them Part::TopoShapePy ::Type.tp_name = "Part.Shape"; @@ -381,5 +383,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 7d6b5e95c6..7707d75aac 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 66ee441924..ec119b937e 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" diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 196a70ba17..0e2acee6b7 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -566,18 +566,29 @@ void CmdPartCompJoinFeatures::languageChange() Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); - QAction* cmd0 = a[0]; - cmd0->setText(QApplication::translate("PartCompJoinFeatures", rcCmdMgr.getCommandByName("Part_JoinConnect")->getMenuText())); - cmd0->setToolTip(QApplication::translate("Part_JoinConnect", rcCmdMgr.getCommandByName("Part_JoinConnect")->getToolTipText())); - cmd0->setStatusTip(QApplication::translate("Part_JoinConnect", rcCmdMgr.getCommandByName("Part_JoinConnect")->getStatusTip())); - QAction* cmd1 = a[1]; - cmd1->setText(QApplication::translate("PartCompJoinFeatures", rcCmdMgr.getCommandByName("Part_JoinEmbed")->getMenuText())); - cmd1->setToolTip(QApplication::translate("Part_JoinEmbed", rcCmdMgr.getCommandByName("Part_JoinEmbed")->getToolTipText())); - cmd1->setStatusTip(QApplication::translate("Part_JoinEmbed", rcCmdMgr.getCommandByName("Part_JoinEmbed")->getStatusTip())); - QAction* cmd2 = a[2]; - cmd2->setText(QApplication::translate("PartCompJoinFeatures", rcCmdMgr.getCommandByName("Part_JoinCutout")->getMenuText())); - cmd2->setToolTip(QApplication::translate("Part_JoinCutout", rcCmdMgr.getCommandByName("Part_JoinCutout")->getToolTipText())); - cmd2->setStatusTip(QApplication::translate("Part_JoinCutout", rcCmdMgr.getCommandByName("Part_JoinCutout")->getStatusTip())); + Gui::Command* joinConnect = rcCmdMgr.getCommandByName("Part_JoinConnect"); + if (joinConnect) { + QAction* cmd0 = a[0]; + cmd0->setText(QApplication::translate("PartCompJoinFeatures", joinConnect->getMenuText())); + cmd0->setToolTip(QApplication::translate("Part_JoinConnect", joinConnect->getToolTipText())); + cmd0->setStatusTip(QApplication::translate("Part_JoinConnect", joinConnect->getStatusTip())); + } + + Gui::Command* joinEmbed = rcCmdMgr.getCommandByName("Part_JoinEmbed"); + if (joinEmbed) { + QAction* cmd1 = a[1]; + cmd1->setText(QApplication::translate("PartCompJoinFeatures", joinEmbed->getMenuText())); + cmd1->setToolTip(QApplication::translate("Part_JoinEmbed", joinEmbed->getToolTipText())); + cmd1->setStatusTip(QApplication::translate("Part_JoinEmbed", joinEmbed->getStatusTip())); + } + + Gui::Command* joinCutout = rcCmdMgr.getCommandByName("Part_JoinCutout"); + if (joinCutout) { + QAction* cmd2 = a[2]; + cmd2->setText(QApplication::translate("PartCompJoinFeatures", joinCutout->getMenuText())); + cmd2->setToolTip(QApplication::translate("Part_JoinCutout", joinCutout->getToolTipText())); + cmd2->setStatusTip(QApplication::translate("Part_JoinCutout", joinCutout->getStatusTip())); + } } bool CmdPartCompJoinFeatures::isActive(void) diff --git a/src/Mod/PartDesign/App/AppPartDesign.cpp b/src/Mod/PartDesign/App/AppPartDesign.cpp index ee6f6c0606..18f96394c4 100644 --- a/src/Mod/PartDesign/App/AppPartDesign.cpp +++ b/src/Mod/PartDesign/App/AppPartDesign.cpp @@ -49,15 +49,12 @@ #include "FeatureMultiTransform.h" #include "FeatureHole.h" -extern struct PyMethodDef PartDesign_methods[]; - -PyDoc_STRVAR(module_PartDesign_doc, -"This module is the PartDesign module."); - +namespace PartDesign { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void PartDesignExport init_PartDesign() +PyMODINIT_FUNC init_PartDesign() { // load dependent module try { @@ -68,7 +65,8 @@ void PartDesignExport init_PartDesign() PyErr_SetString(PyExc_ImportError, e.what()); return; } - Py_InitModule3("_PartDesign", PartDesign_methods, module_PartDesign_doc); /* mod name, table ptr */ + + (void)PartDesign::initModule(); Base::Console().Log("Loading PartDesign module... done\n"); @@ -97,5 +95,3 @@ void PartDesignExport init_PartDesign() PartDesign::Chamfer ::init(); PartDesign::Draft ::init(); } - -} // extern "C" diff --git a/src/Mod/PartDesign/App/AppPartDesignPy.cpp b/src/Mod/PartDesign/App/AppPartDesignPy.cpp index d6da54513f..c200ab40eb 100644 --- a/src/Mod/PartDesign/App/AppPartDesignPy.cpp +++ b/src/Mod/PartDesign/App/AppPartDesignPy.cpp @@ -26,78 +26,96 @@ # include #endif +#include +#include + #include #include #include -static PyObject * makeFilletArc(PyObject *self, PyObject *args) +namespace PartDesign { +class Module : public Py::ExtensionModule { - PyObject *pM1; - PyObject *pP; - PyObject *pQ; - PyObject *pN; - double r2; - int ccw; - if (!PyArg_ParseTuple(args, "O!O!O!O!di", - &(Base::VectorPy::Type), &pM1, - &(Base::VectorPy::Type), &pP, - &(Base::VectorPy::Type), &pQ, - &(Base::VectorPy::Type), &pN, - &r2, &ccw)) - return NULL; - - Base::Vector3d M1 = Py::Vector(pM1, false).toVector(); - Base::Vector3d P = Py::Vector(pP, false).toVector(); - Base::Vector3d Q = Py::Vector(pQ, false).toVector(); - Base::Vector3d N = Py::Vector(pN, false).toVector(); - - Base::Vector3d u = Q - P; - Base::Vector3d v = P - M1; - Base::Vector3d b; - if (ccw) - b = u % N; - else - b = N % u; - b.Normalize(); - - double uu = u * u; - double uv = u * v; - double r1 = v.Length(); - - // distinguish between internal and external fillets - r2 *= Base::sgn(uv); - - double cc = 2.0 * r2 * (b * v - r1); - double d = uv * uv - uu * cc; - if (d < 0) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "Unable to caluclate intersection points"); - return NULL; +public: + Module() : Py::ExtensionModule("_PartDesign") + { + add_varargs_method("makeFilletArc",&Module::makeFilletArc, + "makeFilletArc(...) -- Fillet arc." + ); + initialize("This module is the PartDesign module."); // register with Python } - double t; - double t1 = (-uv + sqrt(d)) / uu; - double t2 = (-uv - sqrt(d)) / uu; + virtual ~Module() {} - if (fabs(t1) < fabs(t2)) - t = t1; - else - t = t2; +private: + Py::Object makeFilletArc(const Py::Tuple& args) + { + PyObject *pM1; + PyObject *pP; + PyObject *pQ; + PyObject *pN; + double r2; + int ccw; + if (!PyArg_ParseTuple(args.ptr(), "O!O!O!O!di", + &(Base::VectorPy::Type), &pM1, + &(Base::VectorPy::Type), &pP, + &(Base::VectorPy::Type), &pQ, + &(Base::VectorPy::Type), &pN, + &r2, &ccw)) + throw Py::Exception(); - Base::Vector3d M2 = P + (u*t) + (b*r2); - Base::Vector3d S1 = (r2 * M1 + r1 * M2)/(r1+r2); - Base::Vector3d S2 = M2 - (b*r2); + Base::Vector3d M1 = Py::Vector(pM1, false).toVector(); + Base::Vector3d P = Py::Vector(pP, false).toVector(); + Base::Vector3d Q = Py::Vector(pQ, false).toVector(); + Base::Vector3d N = Py::Vector(pN, false).toVector(); - Py::Tuple tuple(3); - tuple.setItem(0, Py::Vector(S1)); - tuple.setItem(1, Py::Vector(S2)); - tuple.setItem(2, Py::Vector(M2)); + Base::Vector3d u = Q - P; + Base::Vector3d v = P - M1; + Base::Vector3d b; + if (ccw) + b = u % N; + else + b = N % u; + b.Normalize(); - return Py::new_reference_to(tuple); + double uu = u * u; + double uv = u * v; + double r1 = v.Length(); + + // distinguish between internal and external fillets + r2 *= Base::sgn(uv); + + double cc = 2.0 * r2 * (b * v - r1); + double d = uv * uv - uu * cc; + if (d < 0) { + throw Py::RuntimeError("Unable to caluclate intersection points"); + } + + double t; + double t1 = (-uv + sqrt(d)) / uu; + double t2 = (-uv - sqrt(d)) / uu; + + if (fabs(t1) < fabs(t2)) + t = t1; + else + t = t2; + + Base::Vector3d M2 = P + (u*t) + (b*r2); + Base::Vector3d S1 = (r2 * M1 + r1 * M2)/(r1+r2); + Base::Vector3d S2 = M2 - (b*r2); + + Py::Tuple tuple(3); + tuple.setItem(0, Py::Vector(S1)); + tuple.setItem(1, Py::Vector(S2)); + tuple.setItem(2, Py::Vector(M2)); + + return tuple; + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef PartDesign_methods[] = { - {"makeFilletArc" ,makeFilletArc,METH_VARARGS, - "makeFilletArc(...) -- Fillet arc."}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace PartDesign diff --git a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp index 6fe67cbcc6..af202d08c2 100644 --- a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp +++ b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -55,13 +58,30 @@ void loadPartDesignResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef PartDesignGui_Import_methods[]; +namespace PartDesignGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("PartDesignGui") + { + initialize("This module is the PartDesignGui module."); // register with Python + } + + virtual ~Module() {} + +private: +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace PartDesignGui /* Python entry */ -extern "C" { -void PartDesignGuiExport initPartDesignGui() +PyMODINIT_FUNC initPartDesignGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -77,7 +97,7 @@ void PartDesignGuiExport initPartDesignGui() return; } - (void) Py_InitModule("PartDesignGui", PartDesignGui_Import_methods); /* mod name, table ptr */ + (void)PartDesignGui::initModule(); Base::Console().Log("Loading GUI of PartDesign module... done\n"); // instantiating the commands @@ -101,5 +121,3 @@ void PartDesignGuiExport initPartDesignGui() // add resources and reloads the translators loadPartDesignResource(); } - -} // extern "C" { diff --git a/src/Mod/PartDesign/Gui/AppPartDesignGuiPy.cpp b/src/Mod/PartDesign/Gui/AppPartDesignGuiPy.cpp deleted file mode 100644 index d184ea1e68..0000000000 --- a/src/Mod/PartDesign/Gui/AppPartDesignGuiPy.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -#endif - - -/* registration table */ -struct PyMethodDef PartDesignGui_Import_methods[] = { - {NULL, NULL} /* end of table marker */ -}; diff --git a/src/Mod/PartDesign/Gui/CMakeLists.txt b/src/Mod/PartDesign/Gui/CMakeLists.txt index ecfec37f02..45743b3060 100644 --- a/src/Mod/PartDesign/Gui/CMakeLists.txt +++ b/src/Mod/PartDesign/Gui/CMakeLists.txt @@ -157,7 +157,6 @@ SOURCE_GROUP("TaskDialogs" FILES ${PartDesignGuiTaskDlgs_SRCS}) SET(PartDesignGuiModule_SRCS AppPartDesignGui.cpp - AppPartDesignGuiPy.cpp Command.cpp Resources/PartDesign.qrc PreCompiled.cpp diff --git a/src/Mod/Path/App/AppPath.cpp b/src/Mod/Path/App/AppPath.cpp index b4fc8f752d..ab6ffe02ec 100644 --- a/src/Mod/Path/App/AppPath.cpp +++ b/src/Mod/Path/App/AppPath.cpp @@ -42,25 +42,22 @@ #include "FeaturePathCompound.h" #include "FeaturePathShape.h" -extern struct PyMethodDef Path_methods[]; - -PyDoc_STRVAR(module_Path_doc, -"This module is the Path module."); - +namespace Path { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void PathExport initPath() +PyMODINIT_FUNC initPath() { - PyObject* pathModule = Py_InitModule3("Path", Path_methods, module_Path_doc); /* mod name, table ptr */ + PyObject* pathModule = Path::initModule(); Base::Console().Log("Loading Path module... done\n"); // Add Types to module - Base::Interpreter().addType(&Path::CommandPy ::Type,pathModule,"Command"); - Base::Interpreter().addType(&Path::PathPy ::Type,pathModule,"Path"); - Base::Interpreter().addType(&Path::ToolPy ::Type,pathModule,"Tool"); - Base::Interpreter().addType(&Path::TooltablePy ::Type,pathModule,"Tooltable"); + Base::Interpreter().addType(&Path::CommandPy ::Type, pathModule, "Command"); + Base::Interpreter().addType(&Path::PathPy ::Type, pathModule, "Path"); + Base::Interpreter().addType(&Path::ToolPy ::Type, pathModule, "Tool"); + Base::Interpreter().addType(&Path::TooltablePy ::Type, pathModule, "Tooltable"); // NOTE: To finish the initialization of our own type objects we must // call PyType_Ready, otherwise we run into a segmentation fault, later on. @@ -78,5 +75,3 @@ void PathExport initPath() Path::FeatureShape ::init(); Path::FeatureShapePython ::init(); } - -} // extern "C" diff --git a/src/Mod/Path/App/AppPathPy.cpp b/src/Mod/Path/App/AppPathPy.cpp index 833144fd3f..b2d167cacd 100644 --- a/src/Mod/Path/App/AppPathPy.cpp +++ b/src/Mod/Path/App/AppPathPy.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -40,103 +43,125 @@ #include "FeaturePath.h" #include "FeaturePathCompound.h" -using namespace Path; - - -static PyObject * write (PyObject *self, PyObject *args) +namespace Path { +class Module : public Py::ExtensionModule { - char* Name; - PyObject* pObj; - if (!PyArg_ParseTuple(args, "Oet",&pObj,"utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - Base::FileInfo file(EncodedName.c_str()); - - if (PyObject_TypeCheck(pObj, &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(pObj)->getDocumentObjectPtr(); - if (obj->getTypeId().isDerivedFrom(Base::Type::fromName("Path::Feature"))) { - const Toolpath& path = static_cast(obj)->Path.getValue(); - std::string gcode = path.toGCode(); - std::ofstream ofile(EncodedName.c_str()); - ofile << gcode; - ofile.close(); - } else - Py_Error(Base::BaseExceptionFreeCADError, "The given file is not a path"); +public: + Module() : Py::ExtensionModule("Path") + { + add_varargs_method("write",&Module::write, + "write(object,filename): Exports a given path object to a GCode file" + ); + add_varargs_method("read",&Module::read, + "read(filename,[document]): Imports a GCode file into the given document" + ); + add_varargs_method("show",&Module::show, + "show(path): Add the path to the active document or create one if no document exists" + ); + initialize("This module is the Path module."); // register with Python } - Py_Return; -} + virtual ~Module() {} -static PyObject * read (PyObject *self, PyObject *args) -{ - char* Name; - const char* DocName=0; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - - Base::FileInfo file(EncodedName.c_str()); - if (!file.exists()) - Py_Error(Base::BaseExceptionFreeCADError, "File doesn't exist"); - App::Document *pcDoc; - if (DocName) - pcDoc = App::GetApplication().getDocument(DocName); - else - pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(DocName); - - PY_TRY { - // read the gcode file - std::ifstream filestr(file.filePath().c_str()); - std::stringstream buffer; - buffer << filestr.rdbuf(); - std::string gcode = buffer.str(); - Toolpath path; - path.setFromGCode(gcode); - Path::Feature *object = static_cast(pcDoc->addObject("Path::Feature",file.fileNamePure().c_str())); - object->Path.setValue(path); - pcDoc->recompute(); - } PY_CATCH; - Py_Return; -} - - -static PyObject * show (PyObject *self, PyObject *args) -{ - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O!", &(PathPy::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(); - PathPy* pPath = static_cast(pcObj); - Path::Feature *pcFeature = (Path::Feature *)pcDoc->addObject("Path::Feature", "Path"); - Path::Toolpath* pa = pPath->getToolpathPtr(); - if (!pa) { - PyErr_SetString(PyExc_ReferenceError, - "object doesn't reference a valid path"); - return 0; +private: + Py::Object write(const Py::Tuple& args) + { + char* Name; + PyObject* pObj; + if (!PyArg_ParseTuple(args.ptr(), "Oet",&pObj,"utf-8",&Name)) + throw Py::Exception(); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + Base::FileInfo file(EncodedName.c_str()); + + if (PyObject_TypeCheck(pObj, &(App::DocumentObjectPy::Type))) { + App::DocumentObject* obj = static_cast(pObj)->getDocumentObjectPtr(); + if (obj->getTypeId().isDerivedFrom(Base::Type::fromName("Path::Feature"))) { + const Toolpath& path = static_cast(obj)->Path.getValue(); + std::string gcode = path.toGCode(); + std::ofstream ofile(EncodedName.c_str()); + ofile << gcode; + ofile.close(); + } + else { + throw Py::RuntimeError("The given file is not a path"); + } } - // copy the data - pcFeature->Path.setValue(*pa); - } PY_CATCH; - Py_Return; + return Py::None(); + } + + Py::Object read(const Py::Tuple& args) + { + char* Name; + const char* DocName=0; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + Base::FileInfo file(EncodedName.c_str()); + if (!file.exists()) + throw Py::RuntimeError("File doesn't exist"); + + App::Document *pcDoc; + if (DocName) + pcDoc = App::GetApplication().getDocument(DocName); + else + pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(DocName); + + try { + // read the gcode file + std::ifstream filestr(file.filePath().c_str()); + std::stringstream buffer; + buffer << filestr.rdbuf(); + std::string gcode = buffer.str(); + Toolpath path; + path.setFromGCode(gcode); + Path::Feature *object = static_cast(pcDoc->addObject("Path::Feature",file.fileNamePure().c_str())); + object->Path.setValue(path); + pcDoc->recompute(); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + return Py::None(); + } + + Py::Object show(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O!", &(PathPy::Type), &pcObj)) + throw Py::Exception(); + + try { + App::Document *pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(); + PathPy* pPath = static_cast(pcObj); + Path::Feature *pcFeature = (Path::Feature *)pcDoc->addObject("Path::Feature", "Path"); + Path::Toolpath* pa = pPath->getToolpathPtr(); + if (!pa) { + throw Py::Exception(PyExc_ReferenceError, "object doesn't reference a valid path"); + } + + // copy the data + pcFeature->Path.setValue(*pa); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } - -/* registration table */ -struct PyMethodDef Path_methods[] = { - {"write" ,write ,METH_VARARGS, - "write(object,filename): Exports a given path object to a GCode file"}, - {"read" ,read ,METH_VARARGS, - "read(filename,[document]): Imports a GCode file into the given document"}, - {"show" ,show ,METH_VARARGS, - "show(path): Add the path to the active document or create one if no document exists."}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace Path diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index f53f4b4079..1de3dac479 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -50,6 +50,12 @@ SET(PathScripts_SRCS PathScripts/PathKurveUtils.py PathScripts/PathKurve.py PathScripts/slic3r_pre.py + PathScripts/PathFaceProfile.py + PathScripts/PathFacePocket.py + PathScripts/PathArray.py + PathScripts/PathCustom.py + PathScripts/PathInspect.py + PathScripts/PathSimpleCopy.py ) ADD_CUSTOM_TARGET(PathScripts ALL diff --git a/src/Mod/Path/Gui/AppPathGui.cpp b/src/Mod/Path/Gui/AppPathGui.cpp index 3d10c27f16..74fe4ce624 100644 --- a/src/Mod/Path/Gui/AppPathGui.cpp +++ b/src/Mod/Path/Gui/AppPathGui.cpp @@ -46,13 +46,12 @@ void loadPathResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef PathGui_methods[]; - +namespace PathGui { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void PathGuiExport initPathGui() +PyMODINIT_FUNC initPathGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -65,7 +64,7 @@ void PathGuiExport initPathGui() PyErr_SetString(PyExc_ImportError, e.what()); return; } - (void) Py_InitModule("PathGui", PathGui_methods); /* mod name, table ptr */ + (void)PathGui::initModule(); Base::Console().Log("Loading GUI of Path module... done\n"); // instantiating the commands @@ -84,5 +83,3 @@ void PathGuiExport initPathGui() // register preferences pages new Gui::PrefPageProducer ("Path"); } - -} // extern "C" { diff --git a/src/Mod/Path/Gui/AppPathGuiPy.cpp b/src/Mod/Path/Gui/AppPathGuiPy.cpp index a956ae58c3..6fd3e6e9a4 100644 --- a/src/Mod/Path/Gui/AppPathGuiPy.cpp +++ b/src/Mod/Path/Gui/AppPathGuiPy.cpp @@ -25,6 +25,9 @@ # include #endif +#include +#include + #include #include @@ -43,215 +46,248 @@ #include "DlgProcessorChooser.h" #include "ui_DlgProcessorChooser.h" -using namespace PathGui; - -static PyObject * open(PyObject *self, PyObject *args) +namespace PathGui { +class Module : public Py::ExtensionModule { - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - Base::FileInfo fi(EncodedName); - if (!fi.exists()) - Py_Error(Base::BaseExceptionFreeCADError, "File not found"); - Gui::WaitCursor wc; - wc.restoreCursor(); +public: + Module() : Py::ExtensionModule("PathGui") + { + add_varargs_method("open",&Module::open, + "open(filename): Opens a GCode file as a new document" + ); + add_varargs_method("insert",&Module::insert, + "insert(filename,docname): Imports a given GCode file into the given document" + ); + add_varargs_method("export",&Module::exporter, + "export(objectslist,filename): Exports a given list of Path objects to a GCode file" + ); + initialize("This module is the PathGui module."); // register with Python + } - PY_TRY { - std::string path = App::GetApplication().getHomePath(); - path += "Mod/Path/PathScripts/"; - QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); - std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") - ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); - QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_pre.py")); - QFileInfoList list = dir1.entryInfoList(); - list << dir2.entryInfoList(); - std::vector scripts; - for (int i = 0; i < list.size(); ++i) { - QFileInfo fileInfo = list.at(i); - scripts.push_back(fileInfo.baseName().toStdString()); - } - std::string selected; - PathGui::DlgProcessorChooser Dlg(scripts); - if (Dlg.exec() != QDialog::Accepted) { - Py_Return; - } - selected = Dlg.getSelected(); - - std::ostringstream pre; - std::ostringstream cmd; - if (selected.empty()) { - App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); - Gui::Command::runCommand(Gui::Command::Gui,"import Path"); - cmd << "Path.read(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); - } else { + virtual ~Module() {} + +private: + 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::FileInfo fi(EncodedName); + if (!fi.exists()) + throw Py::RuntimeError("File not found"); + + Gui::WaitCursor wc; + wc.restoreCursor(); + + try { + std::string path = App::GetApplication().getHomePath(); + path += "Mod/Path/PathScripts/"; + QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); + std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") + ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); + QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_pre.py")); + QFileInfoList list = dir1.entryInfoList(); + list << dir2.entryInfoList(); + std::vector scripts; for (int i = 0; i < list.size(); ++i) { QFileInfo fileInfo = list.at(i); - if (fileInfo.baseName().toStdString() == selected) { - if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { - pre << "from PathScripts import " << selected; - } else { - pre << "import " << selected; - } - Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); - cmd << selected << ".open(\"" << EncodedName << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); - } + scripts.push_back(fileInfo.baseName().toStdString()); } - } - } PY_CATCH; - Py_Return; -} - -static PyObject * importer(PyObject *self, PyObject *args) -{ - char* Name; - char* DocName=0; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - Base::FileInfo fi(EncodedName); - if (!fi.exists()) - Py_Error(Base::BaseExceptionFreeCADError, "File not found"); - Gui::WaitCursor wc; - wc.restoreCursor(); - - PY_TRY { - std::string path = App::GetApplication().getHomePath(); - path += "Mod/Path/PathScripts/"; - QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); - std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") - ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); - QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_pre.py")); - QFileInfoList list = dir1.entryInfoList(); - list << dir2.entryInfoList(); - std::vector scripts; - for (int i = 0; i < list.size(); ++i) { - QFileInfo fileInfo = list.at(i); - scripts.push_back(fileInfo.baseName().toStdString()); - } - std::string selected; - PathGui::DlgProcessorChooser Dlg(scripts); - if (Dlg.exec() != QDialog::Accepted) { - Py_Return; - } - selected = Dlg.getSelected(); - - App::Document *pcDoc = 0; - if (DocName) - pcDoc = App::GetApplication().getDocument(DocName); - else - pcDoc = App::GetApplication().getActiveDocument(); - - if (!pcDoc) { - pcDoc = App::GetApplication().newDocument(DocName); - } - - std::ostringstream pre; - std::ostringstream cmd; - if (selected.empty()) { - Gui::Command::runCommand(Gui::Command::Gui,"import Path"); - cmd << "Path.read(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); - } else { - for (int i = 0; i < list.size(); ++i) { - QFileInfo fileInfo = list.at(i); - if (fileInfo.baseName().toStdString() == selected) { - if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { - pre << "from PathScripts import " << selected; - } else { - pre << "import " << selected; - } - Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); - cmd << selected << ".insert(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); - } + std::string selected; + PathGui::DlgProcessorChooser Dlg(scripts); + if (Dlg.exec() != QDialog::Accepted) { + return Py::None(); } - } - } PY_CATCH; - Py_Return; -} - -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); - Gui::WaitCursor wc; - wc.restoreCursor(); - - PY_TRY { - Py::Sequence objlist(object); - if (objlist.size() == 0) - Py_Error(Base::BaseExceptionFreeCADError, "No object to export"); - std::string path = App::GetApplication().getHomePath(); - path += "Mod/Path/PathScripts/"; - QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_post.py")); - std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") - ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); - QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_post.py")); - QFileInfoList list = dir1.entryInfoList(); - list << dir2.entryInfoList(); - std::vector scripts; - for (int i = 0; i < list.size(); ++i) { - QFileInfo fileInfo = list.at(i); - scripts.push_back(fileInfo.baseName().toStdString()); - } - std::string selected; - PathGui::DlgProcessorChooser Dlg(scripts); - if (Dlg.exec() != QDialog::Accepted) { - Py_Return; - } - selected = Dlg.getSelected(); - - std::ostringstream pre; - std::ostringstream cmd; - if (selected.empty()) { - if (objlist.size() > 1) { - Py_Error(Base::BaseExceptionFreeCADError, "Cannot export more than one object without using a post script"); - } - PyObject* item = objlist[0].ptr(); - if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr(); - App::Document* doc = obj->getDocument(); + selected = Dlg.getSelected(); + + std::ostringstream pre; + std::ostringstream cmd; + if (selected.empty()) { + App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); Gui::Command::runCommand(Gui::Command::Gui,"import Path"); - cmd << "Path.write(FreeCAD.getDocument(\"" << doc->getName() << "\").getObject(\"" << obj->getNameInDocument() << "\"),\"" << EncodedName << "\")"; + cmd << "Path.read(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); } else { - Py_Return; - } - } else { - for (int i = 0; i < list.size(); ++i) { - QFileInfo fileInfo = list.at(i); - if (fileInfo.baseName().toStdString() == selected) { - if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { - pre << "from PathScripts import " << selected; - } else { - pre << "import " << selected; + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + if (fileInfo.baseName().toStdString() == selected) { + if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { + pre << "from PathScripts import " << selected; + } else { + pre << "import " << selected; + } + Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); + cmd << selected << ".open(\"" << EncodedName << "\")"; + Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); } - Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); - cmd << selected << ".export(__objs__,\"" << EncodedName << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); } } } - } PY_CATCH; - Py_Return; + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + return Py::None(); + } + + Py::Object insert(const Py::Tuple& args) + { + char* Name; + char* DocName=0; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + Base::FileInfo fi(EncodedName); + if (!fi.exists()) + throw Py::RuntimeError("File not found"); + + Gui::WaitCursor wc; + wc.restoreCursor(); + + try { + std::string path = App::GetApplication().getHomePath(); + path += "Mod/Path/PathScripts/"; + QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); + std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") + ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); + QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_pre.py")); + QFileInfoList list = dir1.entryInfoList(); + list << dir2.entryInfoList(); + std::vector scripts; + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + scripts.push_back(fileInfo.baseName().toStdString()); + } + std::string selected; + PathGui::DlgProcessorChooser Dlg(scripts); + if (Dlg.exec() != QDialog::Accepted) { + return Py::None(); + } + selected = Dlg.getSelected(); + + App::Document *pcDoc = 0; + if (DocName) + pcDoc = App::GetApplication().getDocument(DocName); + else + pcDoc = App::GetApplication().getActiveDocument(); + + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument(DocName); + } + + std::ostringstream pre; + std::ostringstream cmd; + if (selected.empty()) { + Gui::Command::runCommand(Gui::Command::Gui,"import Path"); + cmd << "Path.read(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; + Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); + } else { + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + if (fileInfo.baseName().toStdString() == selected) { + if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { + pre << "from PathScripts import " << selected; + } else { + pre << "import " << selected; + } + Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); + cmd << selected << ".insert(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; + Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); + } + } + } + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + 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); + Gui::WaitCursor wc; + wc.restoreCursor(); + + try { + Py::Sequence objlist(object); + if (objlist.size() == 0) + throw Py::RuntimeError("No object to export"); + + std::string path = App::GetApplication().getHomePath(); + path += "Mod/Path/PathScripts/"; + QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_post.py")); + std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") + ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); + QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_post.py")); + QFileInfoList list = dir1.entryInfoList(); + list << dir2.entryInfoList(); + std::vector scripts; + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + scripts.push_back(fileInfo.baseName().toStdString()); + } + std::string selected; + PathGui::DlgProcessorChooser Dlg(scripts); + if (Dlg.exec() != QDialog::Accepted) { + return Py::None(); + } + selected = Dlg.getSelected(); + + std::ostringstream pre; + std::ostringstream cmd; + if (selected.empty()) { + if (objlist.size() > 1) { + throw Py::RuntimeError("Cannot export more than one object without using a post script"); + } + PyObject* item = objlist[0].ptr(); + if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) { + App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr(); + App::Document* doc = obj->getDocument(); + Gui::Command::runCommand(Gui::Command::Gui,"import Path"); + cmd << "Path.write(FreeCAD.getDocument(\"" << doc->getName() << "\").getObject(\"" << obj->getNameInDocument() << "\"),\"" << EncodedName << "\")"; + Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); + } else { + return Py::None(); + } + } else { + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + if (fileInfo.baseName().toStdString() == selected) { + if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { + pre << "from PathScripts import " << selected; + } else { + pre << "import " << selected; + } + Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); + cmd << selected << ".export(__objs__,\"" << EncodedName << "\")"; + Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); + } + } + } + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef PathGui_methods[] = { - {"open" ,open ,METH_VARARGS, - "open(filename): Opens a GCode file as a new document"}, - {"insert" ,importer ,METH_VARARGS, - "insert(filename,docname): Imports a given GCode file into the given document"}, - {"export" ,exporter ,METH_VARARGS, - "export(objectslist,filename): Exports a given list of Path objects to a GCode file"}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace PathGui diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc index 6d70808611..9a5c60c0b0 100644 --- a/src/Mod/Path/Gui/Resources/Path.qrc +++ b/src/Mod/Path/Gui/Resources/Path.qrc @@ -23,5 +23,12 @@ icons/Path-Stop.svg icons/Path-Machine.svg icons/Path-Kurve.svg + icons/Path-FaceProfile.svg + icons/Path-FacePocket.svg + icons/Path-Array.svg + icons/Path-Custom.svg + icons/Path-Inspect.svg + icons/Path-ToolChange.svg + icons/Path-SimpleCopy.svg diff --git a/src/Mod/Path/Gui/Resources/icons/Path-Array.svg b/src/Mod/Path/Gui/Resources/icons/Path-Array.svg new file mode 100644 index 0000000000..05f99c4e79 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/icons/Path-Array.svg @@ -0,0 +1,533 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/src/Mod/Path/Gui/Resources/icons/Path-Custom.svg b/src/Mod/Path/Gui/Resources/icons/Path-Custom.svg new file mode 100644 index 0000000000..e1c6fdb442 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/icons/Path-Custom.svg @@ -0,0 +1,563 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Path/Gui/Resources/icons/Path-FacePocket.svg b/src/Mod/Path/Gui/Resources/icons/Path-FacePocket.svg new file mode 100644 index 0000000000..bcba5aa8a2 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/icons/Path-FacePocket.svg @@ -0,0 +1,548 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/src/Mod/Path/Gui/Resources/icons/Path-FaceProfile.svg b/src/Mod/Path/Gui/Resources/icons/Path-FaceProfile.svg new file mode 100644 index 0000000000..05429aebf8 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/icons/Path-FaceProfile.svg @@ -0,0 +1,543 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/src/Mod/Path/Gui/Resources/icons/Path-Inspect.svg b/src/Mod/Path/Gui/Resources/icons/Path-Inspect.svg new file mode 100644 index 0000000000..540bada73f --- /dev/null +++ b/src/Mod/Path/Gui/Resources/icons/Path-Inspect.svg @@ -0,0 +1,862 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Path/Gui/Resources/icons/Path-Pocket.svg b/src/Mod/Path/Gui/Resources/icons/Path-Pocket.svg index b984632e5d..f07d14814d 100644 --- a/src/Mod/Path/Gui/Resources/icons/Path-Pocket.svg +++ b/src/Mod/Path/Gui/Resources/icons/Path-Pocket.svg @@ -14,7 +14,7 @@ height="64px" id="svg2816" version="1.1" - inkscape:version="0.48.5 r10040" + inkscape:version="0.91 r13725" sodipodi:docname="Path-Pocket.svg"> @@ -487,9 +487,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="3.8890873" - inkscape:cx="-16.685457" - inkscape:cy="24.803491" + inkscape:zoom="1.9445437" + inkscape:cx="-1.2440898" + inkscape:cy="7.5788627" inkscape:current-layer="layer1" showgrid="true" inkscape:document-units="px" @@ -505,7 +505,8 @@ inkscape:window-height="1053" inkscape:window-x="0" inkscape:window-y="0" - inkscape:window-maximized="1" /> + inkscape:window-maximized="1" + inkscape:snap-global="true" /> @@ -514,7 +515,7 @@ image/svg+xml - + @@ -522,20 +523,32 @@ id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer"> + + + + d="m 4.1534091,8.0397727 0,31.7500003 20.7812499,-23.28125 36.03125,6.40625 0,-14.8750003 -56.8124999,0 z" + id="path4211" /> - + diff --git a/src/Mod/Path/Gui/Resources/icons/Path-Profile.svg b/src/Mod/Path/Gui/Resources/icons/Path-Profile.svg index cd32c85621..2b3a6ab200 100644 --- a/src/Mod/Path/Gui/Resources/icons/Path-Profile.svg +++ b/src/Mod/Path/Gui/Resources/icons/Path-Profile.svg @@ -14,7 +14,7 @@ height="64px" id="svg2816" version="1.1" - inkscape:version="0.48.5 r10040" + inkscape:version="0.91 r13725" sodipodi:docname="Path-Profile.svg"> @@ -487,9 +487,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="11" - inkscape:cx="34.775007" - inkscape:cy="34.723538" + inkscape:zoom="7.7781745" + inkscape:cx="34.742778" + inkscape:cy="31.569873" inkscape:current-layer="layer1" showgrid="true" inkscape:document-units="px" @@ -514,7 +514,7 @@ image/svg+xml - + @@ -523,16 +523,38 @@ inkscape:label="Layer 1" inkscape:groupmode="layer"> + + + + + sodipodi:nodetypes="cccccc" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/Mod/Path/Gui/Resources/icons/Path-ToolChange.svg b/src/Mod/Path/Gui/Resources/icons/Path-ToolChange.svg new file mode 100644 index 0000000000..5adc6e8c29 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/icons/Path-ToolChange.svg @@ -0,0 +1,604 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/Mod/Path/Gui/ViewProviderPath.cpp b/src/Mod/Path/Gui/ViewProviderPath.cpp index cfc449f74d..0974d45e70 100644 --- a/src/Mod/Path/Gui/ViewProviderPath.cpp +++ b/src/Mod/Path/Gui/ViewProviderPath.cpp @@ -81,6 +81,7 @@ ViewProviderPath::ViewProviderPath() ADD_PROPERTY_TYPE(MarkerColor,(mr,mg,mb),"Path",App::Prop_None,"The color of the markers"); ADD_PROPERTY_TYPE(LineWidth,(lwidth),"Path",App::Prop_None,"The line width of this path"); ADD_PROPERTY_TYPE(ShowFirstRapid,(true),"Path",App::Prop_None,"Turns the display of the first rapid move on/off"); + ADD_PROPERTY_TYPE(ShowNodes,(false),"Path",App::Prop_None,"Turns the display of nodes on/off"); pcPathRoot = new Gui::SoFCSelection(); @@ -204,7 +205,7 @@ void ViewProviderPath::onChanged(const App::Property* prop) } else if (prop == &MarkerColor) { const App::Color& c = MarkerColor.getValue(); pcMarkerColor->rgb.setValue(c.r,c.g,c.b); - } else if (prop == &ShowFirstRapid) { + } else if ( (prop == &ShowFirstRapid) || (prop == &ShowNodes) ) { Path::Feature* pcPathObj = static_cast(pcObject); this->updateData(&pcPathObj->Path); } else { @@ -216,7 +217,7 @@ void ViewProviderPath::updateData(const App::Property* prop) { Path::Feature* pcPathObj = static_cast(pcObject); - if ( prop == &pcPathObj->Path) { + if (prop == &pcPathObj->Path) { const Toolpath &tp = pcPathObj->Path.getValue(); if(tp.getSize()==0) @@ -252,7 +253,8 @@ void ViewProviderPath::updateData(const App::Property* prop) markers.push_back(last); // startpoint of path } points.push_back(next); - //markers.push_back(next); // endpoint + if (ShowNodes.getValue() == true) + markers.push_back(next); // endpoint last = next; if ( (name == "G0") || (name == "G00") ) colorindex.push_back(0); // rapid color @@ -277,9 +279,11 @@ void ViewProviderPath::updateData(const App::Property* prop) //double radius = (last - center).Length(); double angle = (next - center).GetAngle(last - center); // BUGGY: not needed anyway? - //Base::Vector3d anorm = (last - center) % (next - center); - //if (anorm.z < 0) - // angle = M_PI - angle; + Base::Vector3d anorm = (last - center) % (next - center); + if ( (anorm.z < 0) && ( (name == "G3") || (name == "G03") ) ) + angle = M_PI * 2 - angle; + if (angle == 0) + angle = M_PI * 2; int segments = 3/(deviation/angle); //we use a rather simple rule here, provisorily for (int j = 1; j < segments; j++) { //std::cout << "vector " << j << std::endl; @@ -293,8 +297,10 @@ void ViewProviderPath::updateData(const App::Property* prop) } //std::cout << "next " << next.x << " , " << next.y << " , " << next.z << std::endl; points.push_back(next); - //markers.push_back(next); // endpoint - //markers.push_back(center); // add a marker at center too + if (ShowNodes.getValue() == true) { + markers.push_back(next); // endpoint + markers.push_back(center); // add a marker at center too + } last = next; colorindex.push_back(1); @@ -314,14 +320,17 @@ void ViewProviderPath::updateData(const App::Property* prop) Base::Vector3d p1(next.x,next.y,last.z); // Base::Vector3d p1(next.x,next.y,r); points.push_back(p1); - //markers.push_back(p1); + if (ShowNodes.getValue() == true) + markers.push_back(p1); colorindex.push_back(0); Base::Vector3d p2(next.x,next.y,r); points.push_back(p2); - //markers.push_back(p2); + if (ShowNodes.getValue() == true) + markers.push_back(p2); colorindex.push_back(0); points.push_back(next); - //markers.push_back(next); + if (ShowNodes.getValue() == true) + markers.push_back(next); colorindex.push_back(1); double q; if (cmd.has("Q")) { @@ -335,7 +344,8 @@ void ViewProviderPath::updateData(const App::Property* prop) } Base::Vector3d p3(next.x,next.y,last.z); points.push_back(p3); - //markers.push_back(p2); + if (ShowNodes.getValue() == true) + markers.push_back(p2); colorindex.push_back(0); } } @@ -354,10 +364,6 @@ void ViewProviderPath::updateData(const App::Property* prop) pcMarkerCoords->point.deleteValues(0); - // putting one marker at each node makes the display awfully slow - // following 2 lines leave just one at the origin - //pcMarkerCoords->point.setNum(1); - //pcMarkerCoords->point.set1Value(0,markers[0].x,markers[0].y,markers[0].z); pcMarkerCoords->point.setNum(markers.size()); for(unsigned int i=0;ipoint.set1Value(i,markers[i].x,markers[i].y,markers[i].z); diff --git a/src/Mod/Path/Gui/ViewProviderPath.h b/src/Mod/Path/Gui/ViewProviderPath.h index 8e14e2d00b..e2ac4bf29c 100644 --- a/src/Mod/Path/Gui/ViewProviderPath.h +++ b/src/Mod/Path/Gui/ViewProviderPath.h @@ -55,6 +55,7 @@ public: App::PropertyColor NormalColor; App::PropertyColor MarkerColor; App::PropertyBool ShowFirstRapid; + App::PropertyBool ShowNodes; void attach(App::DocumentObject *pcObject); void setDisplayMode(const char* ModeName); diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py index 3ba33b1fe3..93d8428ea0 100644 --- a/src/Mod/Path/InitGui.py +++ b/src/Mod/Path/InitGui.py @@ -82,29 +82,31 @@ class PathWorkbench ( Workbench ): from PathScripts import PathMachine from PathScripts import PathFromShape from PathScripts import PathKurve + from PathScripts import PathArray + from PathScripts import PathFaceProfile + from PathScripts import PathFacePocket + from PathScripts import PathCustom + from PathScripts import PathInspect + from PathScripts import PathSimpleCopy # build commands list - commands =["Path_Stock","Path_Plane","Path_Fixture","Path_ToolTableEdit","Path_Profile","Path_Kurve","Path_Pocket","Path_Drilling",\ - "Path_Dressup","Path_Hop","Path_Shape","Path_Copy","Path_CompoundExtended","Path_Project"] - - projcmdlist = ["Path_Project", "Path_ToolTableEdit","Path_Post"] - prepcmdlist = ["Path_Plane","Path_Fixture","Path_LoadTool","Path_ToolLenOffset","Path_Comment","Path_Stop"] - opcmdlist = ["Path_Profile","Path_Kurve","Path_Pocket","Path_Drilling","Path_FromShape"] - modcmdlist = ["Path_Copy","Path_CompoundExtended","Path_Dressup","Path_Hop"] + projcmdlist = ["Path_Project", "Path_ToolTableEdit","Path_Post","Path_Inspect"] + prepcmdlist = ["Path_Plane","Path_Fixture","Path_LoadTool","Path_ToolLenOffset","Path_Comment","Path_Stop", + "Path_FaceProfile","Path_FacePocket","Path_Custom","Path_FromShape"] + opcmdlist = ["Path_Profile","Path_Kurve","Path_Pocket","Path_Drilling"] + modcmdlist = ["Path_Copy","Path_CompoundExtended","Path_Dressup","Path_Hop","Path_Array","Path_SimpleCopy"] # Add commands to menu and toolbar def QT_TRANSLATE_NOOP(scope, text): return text -# self.appendToolbar(QT_TRANSLATE_NOOP("PathWorkbench","Path"),commands) self.appendToolbar(QT_TRANSLATE_NOOP("PathWorkbench","Commands for setting up Project"),projcmdlist) - self.appendToolbar(QT_TRANSLATE_NOOP("PathWorkbench","Prepatory Commands"),prepcmdlist) + self.appendToolbar(QT_TRANSLATE_NOOP("PathWorkbench","Partial Commands"),prepcmdlist) self.appendToolbar(QT_TRANSLATE_NOOP("PathWorkbench","Operations"),opcmdlist) self.appendToolbar(QT_TRANSLATE_NOOP("PathWorkbench","Commands for grouping,copying, and organizing operations"),modcmdlist) -# self.appendMenu(QT_TRANSLATE_NOOP("PathWorkbench","Path"),commands) self.appendMenu([QT_TRANSLATE_NOOP("PathWorkbench","Path"),QT_TRANSLATE_NOOP("Path","Project Setup")],projcmdlist) - self.appendMenu([QT_TRANSLATE_NOOP("PathWorkbench","Path"),QT_TRANSLATE_NOOP("Path","Prepatory Commands")],prepcmdlist) - self.appendMenu([QT_TRANSLATE_NOOP("PathWorkbench","Path"),QT_TRANSLATE_NOOP("Path","New Operation")],opcmdlist) + self.appendMenu([QT_TRANSLATE_NOOP("PathWorkbench","Path"),QT_TRANSLATE_NOOP("Path","Partial Commands")],prepcmdlist) + self.appendMenu([QT_TRANSLATE_NOOP("PathWorkbench","Path"),QT_TRANSLATE_NOOP("Path","New Operations")],opcmdlist) self.appendMenu([QT_TRANSLATE_NOOP("PathWorkbench","Path"),QT_TRANSLATE_NOOP("Path","Path Modification")],modcmdlist) # Add preferences pages @@ -121,6 +123,12 @@ class PathWorkbench ( Workbench ): def Deactivated(self): Msg("Path workbench deactivated\n") + + def ContextMenu(self, recipient): + if len(FreeCADGui.Selection.getSelection()) == 1: + if FreeCADGui.Selection.getSelection()[0].isDerivedFrom("Path::Feature"): + self.appendContextMenu("",["Path_Inspect"]) + Gui.addWorkbench(PathWorkbench()) diff --git a/src/Mod/Path/PathScripts/DlgSettingsPath.ui b/src/Mod/Path/PathScripts/DlgSettingsPath.ui index 6eb41293e4..a8d112f7d4 100644 --- a/src/Mod/Path/PathScripts/DlgSettingsPath.ui +++ b/src/Mod/Path/PathScripts/DlgSettingsPath.ui @@ -31,72 +31,16 @@ - If this is checked, object names will be prefixed with the IFC ID number + If this option is enabled, new paths will automatically be placed in the active project, which will be created if necessary. - Test setting 1 + Automatic project handling + + + true - pathTestSetting1 - - - Mod/Path - - - - - - - - - - - Test setting 2 - - - - - - - A comma-separated list of Ifc entities to exclude from import - - - - - - - - - pathTestSetting2 - - - Mod/Path - - - - - - - - - - - - Test group - - - - - - - - Some IFC viewers don't like objects exported as extrusions. Use this to force all objects to be exported as BREP geometry. - - - Test setting 3 - - - pathTestSetting3 + pathAutoProject Mod/Path @@ -131,11 +75,6 @@ QCheckBox
Gui/PrefWidgets.h
- - Gui::PrefLineEdit - QLineEdit -
Gui/PrefWidgets.h
-
diff --git a/src/Mod/Path/PathScripts/PathArray.py b/src/Mod/Path/PathScripts/PathArray.py new file mode 100644 index 0000000000..c9e9be883f --- /dev/null +++ b/src/Mod/Path/PathScripts/PathArray.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2015 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Path,PathGui +from PySide import QtCore,QtGui + +"""Path Array object and FreeCAD command""" + +# Qt tanslation handling +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig) + + +class ObjectArray: + + + def __init__(self,obj): + obj.addProperty("App::PropertyLink","Base","Path","The path to array") + obj.addProperty("App::PropertyVectorDistance","Offset","Path","The spacing between the array copies") + obj.addProperty("App::PropertyInteger","Copies","Path","The number of copies") + obj.Proxy = self + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + def execute(self,obj): + if obj.Base: + if not obj.Base.isDerivedFrom("Path::Feature"): + return + if not obj.Base.Path: + return + + # build copies + basepath = obj.Base.Path + output = basepath.toGCode() + pl = FreeCAD.Placement() + if obj.Offset != FreeCAD.Vector(): + for i in range(obj.Copies): + pl.move(obj.Offset) + np = Path.Path([cm.transform(pl) for cm in basepath.Commands]) + output += np.toGCode() + + #print output + path = Path.Path(output) + obj.Path = path + + +class ViewProviderArray: + + + def __init__(self,vobj): + vobj.Proxy = self + + def attach(self,vobj): + self.Object = vobj.Object + return + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + def claimChildren(self): + if hasattr(self,"Object"): + if hasattr(self.Object,"Base"): + if self.Object.Base: + return self.Object.Base + return [] + + +class CommandPathArray: + + + def GetResources(self): + return {'Pixmap' : 'Path-Array', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathArray","Array"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathArray","Creates an array from a selected path")} + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + + # check that the selection contains exactly what we want + selection = FreeCADGui.Selection.getSelection() + if len(selection) != 1: + FreeCAD.Console.PrintError(translate("PathArray","Please select exactly one path object\n")) + return + if not(selection[0].isDerivedFrom("Path::Feature")): + FreeCAD.Console.PrintError(translate("PathArray","Please select exactly one path object\n")) + return + + # if everything is ok, execute and register the transaction in the undo/redo stack + FreeCAD.ActiveDocument.openTransaction("Create Array") + FreeCADGui.addModule("PathScripts.PathArray") + FreeCADGui.addModule("PathScripts.PathUtils") + FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Array")') + FreeCADGui.doCommand('PathScripts.PathArray.ObjectArray(obj)') + FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.' + selection[0].Name + ')') + #FreeCADGui.doCommand('PathScripts.PathArray.ViewProviderArray(obj.ViewObject)') + FreeCADGui.doCommand('obj.ViewObject.Proxy = 0') + FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)') + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand('Path_Array',CommandPathArray()) diff --git a/src/Mod/Path/PathScripts/PathCompoundExtended.py b/src/Mod/Path/PathScripts/PathCompoundExtended.py index 229b8db5e0..655accdfc2 100644 --- a/src/Mod/Path/PathScripts/PathCompoundExtended.py +++ b/src/Mod/Path/PathScripts/PathCompoundExtended.py @@ -58,7 +58,11 @@ class ObjectCompoundExtended: cmds = [] for child in obj.Group: if child.isDerivedFrom("Path::Feature"): - cmds.extend(child.Path.Commands) + if obj.UsePlacements: + for c in child.Path.Commands: + cmds.append(c.transform(child.Placement)) + else: + cmds.extend(child.Path.Commands) if cmds: path = Path.Path(cmds) obj.Path = path diff --git a/src/Mod/Path/PathScripts/PathCustom.py b/src/Mod/Path/PathScripts/PathCustom.py new file mode 100644 index 0000000000..3745239ed1 --- /dev/null +++ b/src/Mod/Path/PathScripts/PathCustom.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2014 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Path,PathGui +from PySide import QtCore,QtGui + +"""Path Custom object and FreeCAD command""" + +# Qt tanslation handling +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig) + + +class ObjectCustom: + + + def __init__(self,obj): + obj.addProperty("App::PropertyStringList","Gcode","Path","The gcode to be inserted") + obj.Proxy = self + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + def execute(self,obj): + if obj.Gcode: + s = "" + for l in obj.Gcode: + s += str(l) + if s: + path = Path.Path(s) + obj.Path = path + + +class CommandPathCustom: + + + def GetResources(self): + return {'Pixmap' : 'Path-Custom', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Custom","Custom"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Custom","Creates a path object based on custom G-code")} + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + FreeCAD.ActiveDocument.openTransaction("Create Custom Path") + FreeCADGui.addModule("PathScripts.PathCustom") + FreeCADGui.addModule("PathScripts.PathUtils") + FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Custom")') + FreeCADGui.doCommand('PathScripts.PathCustom.ObjectCustom(obj)') + FreeCADGui.doCommand('obj.ViewObject.Proxy = 0') + FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)') + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand('Path_Custom',CommandPathCustom()) diff --git a/src/Mod/Path/PathScripts/PathFacePocket.py b/src/Mod/Path/PathScripts/PathFacePocket.py new file mode 100644 index 0000000000..772bcc1e47 --- /dev/null +++ b/src/Mod/Path/PathScripts/PathFacePocket.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2014 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Path,PathGui +from PySide import QtCore,QtGui + +"""Path Pocket object and FreeCAD command""" + +# Qt tanslation handling +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig) + + +class ObjectFacePocket: + + + def __init__(self,obj): + obj.addProperty("App::PropertyLinkSub","Base","Path","The base geometry of this object") + obj.addProperty("App::PropertyDistance","Offset","Path","The distance between the face and the path") + obj.addProperty("App::PropertyInteger","StartVertex","Path","The vertex index to start the path from") + obj.addProperty("App::PropertyEnumeration","FirstMove","Path","The type of the first move") + obj.addProperty("App::PropertyDistance","RetractHeight","Path","The height to travel at between loops") + obj.addProperty("App::PropertyBool","Fill","Path","Perform only one loop or fill the whole shape") + obj.FirstMove = ["G0","G1"] + obj.Proxy = self + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + def execute(self,obj): + if obj.Base and obj.Offset.Value: + import Part, DraftGeomUtils + if "Face" in obj.Base[1][0]: + shape = getattr(obj.Base[0].Shape,obj.Base[1][0]) + else: + edges = [getattr(obj.Base[0].Shape,sub) for sub in obj.Base[1]] + shape = Part.Wire(edges) + + # absolute coords, millimeters, cancel offsets + output = "G90\nG21\nG40\n" + + # build offsets + offsets = [] + nextradius = obj.Offset.Value + result = DraftGeomUtils.pocket2d(shape,nextradius) + while result: + offsets.extend(result) + if obj.Fill: + nextradius += obj.Offset.Value + result = DraftGeomUtils.pocket2d(shape,nextradius) + else: + result = [] + + first = True + point = None + + # revert the list so we start with the outer wires + offsets.reverse() + + # loop over successive wires + while offsets: + currentWire = offsets.pop() + if first: + currentWire = DraftGeomUtils.rebaseWire(currentWire,obj.StartVertex) + last = None + for edge in currentWire.Edges: + if not last: + # we set the base GO to our first point + if first: + output += obj.FirstMove + first = False + else: + if obj.RetractHeight.Value and point: + output += "G0 X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % obj.RetractHeight.Value) + "\n" + last = edge.Vertexes[0].Point + output += "G0 X" + str("%f" % last.x) + " Y" + str("%f" % last.y) + " Z" + str("%f" % obj.RetractHeight.Value) + "\n" + output += "G1" + last = edge.Vertexes[0].Point + output += " X" + str("%f" % last.x) + " Y" + str("%f" % last.y) + " Z" + str("%f" % last.z) + "\n" + if isinstance(edge.Curve,Part.Circle): + point = edge.Vertexes[-1].Point + if point == last: # edges can come flipped + point = edge.Vertexes[0].Point + center = edge.Curve.Center + relcenter = center.sub(last) + v1 = last.sub(center) + v2 = point.sub(center) + if edge.Curve.Axis.z < 0: + output += "G2" + else: + output += "G3" + output += " X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z) + output += " I" + str("%f" % relcenter.x) + " J" + str("%f" % relcenter.y) + " K" + str("%f" % relcenter.z) + output += "\n" + last = point + else: + point = edge.Vertexes[-1].Point + if point == last: # edges can come flipped + point = edge.Vertexes[0].Point + output += "G1 X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z) + "\n" + last = point + + #print output + path = Path.Path(output) + obj.Path = path + + +class CommandPathFacePocket: + + + def GetResources(self): + return {'Pixmap' : 'Path-FacePocket', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathFacePocket","Face Pocket"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathFacePocket","Creates a pocket inside a loop of edges or a face")} + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + + # check that the selection contains exactly what we want + selection = FreeCADGui.Selection.getSelectionEx() + if len(selection) != 1: + FreeCAD.Console.PrintError(translate("PathFacePocket","Please select an edges loop from one object, or a single face\n")) + return + if len(selection[0].SubObjects) == 0: + FreeCAD.Console.PrintError(translate("PathFacePocket","Please select an edges loop from one object, or a single face\n")) + return + for s in selection[0].SubObjects: + if s.ShapeType != "Edge": + if (s.ShapeType != "Face") or (len(selection[0].SubObjects) != 1): + FreeCAD.Console.PrintError(translate("PathFacePocket","Please select only edges or a single face\n")) + return + if selection[0].SubObjects[0].ShapeType == "Edge": + try: + import Part + w = Part.Wire(selection[0].SubObjects) + except: + FreeCAD.Console.PrintError(translate("PathFacePocket","The selected edges don't form a loop\n")) + return + + # if everything is ok, execute and register the transaction in the undo/redo stack + FreeCAD.ActiveDocument.openTransaction("Create Pocket") + FreeCADGui.addModule("PathScripts.PathFacePocket") + FreeCADGui.addModule("PathScripts.PathUtils") + FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","FacePocket")') + FreeCADGui.doCommand('PathScripts.PathFacePocket.ObjectFacePocket(obj)') + subs = "[" + for s in selection[0].SubElementNames: + subs += '"' + s + '",' + subs += "]" + FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.' + selection[0].ObjectName + ',' + subs + ')') + FreeCADGui.doCommand('obj.ViewObject.Proxy = 0') + FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)') + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand('Path_FacePocket',CommandPathFacePocket()) diff --git a/src/Mod/Path/PathScripts/PathFaceProfile.py b/src/Mod/Path/PathScripts/PathFaceProfile.py new file mode 100644 index 0000000000..b5beeec4bd --- /dev/null +++ b/src/Mod/Path/PathScripts/PathFaceProfile.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2014 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Path,PathGui +from PySide import QtCore,QtGui + +"""Path Profile object and FreeCAD command""" + +# Qt tanslation handling +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig) + + +class ObjectFaceProfile: + + + def __init__(self,obj): + obj.addProperty("App::PropertyLinkSub","Base","Path","The base geometry of this object") + obj.addProperty("App::PropertyDistance","Offset","Path","The distance between the face and the path") + obj.addProperty("App::PropertyInteger","StartVertex","Path","The vertex index to start the path from") + obj.addProperty("App::PropertyEnumeration","FirstMove","Path","The type of the first move") + obj.FirstMove = ["G0","G1"] + obj.Proxy = self + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + def execute(self,obj): + if obj.Base: + import Part,DraftGeomUtils + # we only consider the outer wire if this is a Face + shape = getattr(obj.Base[0].Shape,obj.Base[1][0]) + if shape.ShapeType == "Wire": + wire = shape + else: + wire = shape.OuterWire + # we use the OCC offset feature + if obj.Offset.Value != 0: + offset = wire.makeOffset(obj.Offset.Value) + else: + offset = wire + # absolute coords, millimeters, cancel offsets + output = "G90\nG21\nG40\n" + # reorder the wire + offset = DraftGeomUtils.rebaseWire(offset,obj.StartVertex) + # we create the path from the offset shape + last = None + for edge in offset.Edges: + if not last: + # we set the first move to our first point + last = edge.Vertexes[0].Point + output += obj.FirstMove + " X" + str("%f" % last.x) + " Y" + str("%f" % last.y) + " Z" + str("%f" % last.z) + "\n" + if isinstance(edge.Curve,Part.Circle): + point = edge.Vertexes[-1].Point + if point == last: # edges can come flipped + point = edge.Vertexes[0].Point + center = edge.Curve.Center + relcenter = center.sub(last) + v1 = last.sub(center) + v2 = point.sub(center) + if v1.cross(v2).z < 0: + output += "G2" + else: + output += "G3" + output += " X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z) + output += " I" + str("%f" % relcenter.x) + " J" + str("%f" % relcenter.y) + " K" + str("%f" % relcenter.z) + output += "\n" + last = point + else: + point = edge.Vertexes[-1].Point + if point == last: # edges can come flipped + point = edge.Vertexes[0].Point + output += "G1 X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z) + "\n" + last = point + #print output + path = Path.Path(output) + obj.Path = path + + +class CommandPathFaceProfile: + + + def GetResources(self): + return {'Pixmap' : 'Path-FaceProfile', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathFaceProfile","Face Profile"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathFaceProfile","Creates a profile object around a selected face")} + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + + # check that the selection contains exactly what we want + selection = FreeCADGui.Selection.getSelectionEx() + if len(selection) != 1: + FreeCAD.Console.PrintError(translate("PathFaceProfile","Please select one face or wire\n")) + return + if len(selection[0].SubObjects) != 1: + FreeCAD.Console.PrintError(translate("PathFaceProfile","Please select only one face or wire\n")) + return + if not selection[0].SubObjects[0].ShapeType in ["Face","Wire"]: + FreeCAD.Console.PrintError(translate("PathFaceProfile","Please select only a face or a wire\n")) + return + + # if everything is ok, execute and register the transaction in the undo/redo stack + FreeCAD.ActiveDocument.openTransaction("Create Profile") + FreeCADGui.addModule("PathScripts.PathFaceProfile") + FreeCADGui.addModule("PathScripts.PathUtils") + FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","FaceProfile")') + FreeCADGui.doCommand('PathScripts.PathFaceProfile.ObjectFaceProfile(obj)') + FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.'+selection[0].ObjectName+',"'+selection[0].SubElementNames[0]+'")') + FreeCADGui.doCommand('obj.ViewObject.Proxy = 0') + FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)') + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand('Path_FaceProfile',CommandPathFaceProfile()) diff --git a/src/Mod/Path/PathScripts/PathFromShape.py b/src/Mod/Path/PathScripts/PathFromShape.py index 21518197de..37fc149c92 100644 --- a/src/Mod/Path/PathScripts/PathFromShape.py +++ b/src/Mod/Path/PathScripts/PathFromShape.py @@ -36,7 +36,10 @@ except AttributeError: def translate(context, text, disambig=None): return QtGui.QApplication.translate(context, text, disambig) +#TODO make the shape parametric class FromShape: + + def __init__(self,obj): obj.addProperty("App::PropertyLink","Base","Shape",translate("Shape Object","The base Shape of this toolpath")) obj.Proxy = self @@ -53,6 +56,7 @@ class FromShape: class _ViewProviderFromShape: + def __init__(self,vobj): #mandatory vobj.Proxy = self @@ -72,37 +76,32 @@ class _ViewProviderFromShape: class CommandFromShape: def GetResources(self): return {'Pixmap' : 'Path-Shape', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathFromShape","Gcode from a Shape"), + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_FromShape","Path from a Shape"), 'Accel': "P, S", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathFromShape","Creates GCode from a FreeCAD wire/curve")} + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_FromShape","Creates a Path from a wire/curve")} def IsActive(self): return not FreeCAD.ActiveDocument is None def Activated(self): - FreeCAD.ActiveDocument.openTransaction(translate("PathFromShape","Create GCode from a wire/curve")) - FreeCADGui.addModule("PathScripts.PathFromShape") - - consolecode = ''' -import Path -import PathScripts -from PathScripts import PathFromShape -from PathScripts import PathUtils - -obj = FreeCAD.activeDocument().addObject('Path::FeatureShape','PathShape') -obj.Shape= FreeCAD.activeDocument().Rectangle.Shape.copy() - -PathUtils.addToProject(obj) - -PathScripts.PathFromShape._ViewProviderFromShape(obj.ViewObject) -App.ActiveDocument.recompute() -''' - FreeCADGui.doCommand(consolecode) + + # check that the selection contains exactly what we want + selection = FreeCADGui.Selection.getSelection() + if len(selection) != 1: + FreeCAD.Console.PrintError(translate("Path_FromShape","Please select exactly one Part-based object\n")) + return + if not(selection[0].isDerivedFrom("Part::Feature")): + FreeCAD.Console.PrintError(translate("Path_FromShape","Please select exactly one Part-based object\n")) + return + + FreeCAD.ActiveDocument.openTransaction(translate("Path_FromShape","Create path from shape")) + FreeCADGui.addModule("PathScripts.PathUtils") + FreeCADGui.doCommand("obj = FreeCAD.activeDocument().addObject('Path::FeatureShape','PathShape')") + FreeCADGui.doCommand("obj.Shape = FreeCAD.activeDocument()."+selection[0].Name+".Shape") + FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)') FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() if FreeCAD.GuiUp: # register the FreeCAD command FreeCADGui.addCommand('Path_FromShape',CommandFromShape()) - -FreeCAD.Console.PrintLog("Loading PathFromShape... done\n") diff --git a/src/Mod/Path/PathScripts/PathHop.py b/src/Mod/Path/PathScripts/PathHop.py index 7d90b2af97..a8b11ef8d5 100644 --- a/src/Mod/Path/PathScripts/PathHop.py +++ b/src/Mod/Path/PathScripts/PathHop.py @@ -121,6 +121,7 @@ class CommandPathHop: FreeCAD.ActiveDocument.openTransaction(translate("PathHop","Create Hop")) FreeCADGui.addModule("PathScripts.PathHop") + FreeCADGui.addModule("PathScripts.PathUtils") FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Hop")') FreeCADGui.doCommand('PathScripts.PathHop.ObjectHop(obj)') FreeCADGui.doCommand('PathScripts.PathHop.ViewProviderPathHop(obj.ViewObject)') diff --git a/src/Mod/Path/PathScripts/PathInspect.py b/src/Mod/Path/PathScripts/PathInspect.py new file mode 100644 index 0000000000..f97ec7c251 --- /dev/null +++ b/src/Mod/Path/PathScripts/PathInspect.py @@ -0,0 +1,192 @@ +#*************************************************************************** +#* (c) Yorik van Havre (yorik@uncreated.net) 2015 * +#* * +#* This file is part of the FreeCAD CAx development system. * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* FreeCAD is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Lesser General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with FreeCAD; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#***************************************************************************/ + + +from PySide import QtCore, QtGui +import FreeCAD,FreeCADGui + + +# Qt tanslation handling +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig) + + +class OldHighlighter(QtGui.QSyntaxHighlighter): + + + def highlightBlock(self, text): + + myClassFormat = QtGui.QTextCharFormat() + myClassFormat.setFontWeight(QtGui.QFont.Bold) + myClassFormat.setForeground(QtCore.Qt.green) + # the regex pattern to be colored + pattern = "(G.*?|M.*?)\\s" + expression = QtCore.QRegExp(pattern) + index = text.index(expression) + while index >= 0: + length = expression.matchedLength() + setFormat(index, length, myClassFormat) + index = text.index(expression, index + length) + + +class GCodeHighlighter(QtGui.QSyntaxHighlighter): + + + def __init__(self, parent=None): + + def convertcolor(c): + return QtGui.QColor(int((c>>24)&0xFF),int((c>>16)&0xFF),int((c>>8)&0xFF)) + + super(GCodeHighlighter, self).__init__(parent) + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor") + colors = [] + c = p.GetUnsigned("Number") + if c: + colors.append(convertcolor(c)) + else: + colors.append(QtCore.Qt.red) + c = p.GetUnsigned("Keyword") + if c: + colors.append(convertcolor(c)) + else: + colors.append(QtGui.QColor(0,170,0)) + c = p.GetUnsigned("Define name") + if c: + colors.append(convertcolor(c)) + else: + colors.append(QtGui.QColor(160,160,164)) + + self.highlightingRules = [] + numberFormat = QtGui.QTextCharFormat() + numberFormat.setForeground(colors[0]) + self.highlightingRules.append((QtCore.QRegExp("[\\-0-9\\.]"),numberFormat)) + keywordFormat = QtGui.QTextCharFormat() + keywordFormat.setForeground(colors[1]) + keywordFormat.setFontWeight(QtGui.QFont.Bold) + keywordPatterns = ["\\bG[0-9]+\\b", "\\bM[0-9]+\\b"] + self.highlightingRules.extend([(QtCore.QRegExp(pattern), keywordFormat) for pattern in keywordPatterns]) + speedFormat = QtGui.QTextCharFormat() + speedFormat.setFontWeight(QtGui.QFont.Bold) + speedFormat.setForeground(colors[2]) + self.highlightingRules.append((QtCore.QRegExp("\\bF[0-9\\.]+\\b"),speedFormat)) + + def highlightBlock(self, text): + + for pattern, format in self.highlightingRules: + expression = QtCore.QRegExp(pattern) + index = expression.indexIn(text) + while index >= 0: + length = expression.matchedLength() + self.setFormat(index, length, format) + index = expression.indexIn(text, index + length) + + +class GCodeEditorDialog(QtGui.QDialog): + + + def __init__(self, parent = FreeCADGui.getMainWindow()): + + QtGui.QDialog.__init__(self,parent) + layout = QtGui.QVBoxLayout(self) + + # nice text editor widget for editing the gcode + self.editor = QtGui.QTextEdit() + font = QtGui.QFont() + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor") + font.setFamily(p.GetString("Font","Courier")) + font.setFixedPitch(True) + font.setPointSize(p.GetInt("FontSize",10)) + self.editor.setFont(font) + self.editor.setText("G01 X55 Y4.5 F300.0") + self.highlighter = GCodeHighlighter(self.editor.document()) + layout.addWidget(self.editor) + + # Note + lab = QtGui.QLabel() + lab.setText(translate("PathInspect","Note: Pressing OK will commit any change you make above to the object, but if the object is parametric, these changes will be overridden on recompute.")) + lab.setWordWrap(True) + layout.addWidget(lab) + + # OK and Cancel buttons + self.buttons = QtGui.QDialogButtonBox( + QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel, + QtCore.Qt.Horizontal, self) + layout.addWidget(self.buttons) + self.buttons.accepted.connect(self.accept) + self.buttons.rejected.connect(self.reject) + + +def show(obj): + + "show(obj): shows the G-code data of the given Path object in a dialog" + + if hasattr(obj,"Path"): + if obj.Path: + dia = GCodeEditorDialog() + dia.editor.setText(obj.Path.toGCode()) + result = dia.exec_() + # exec_() returns 0 or 1 depending on the button pressed (Ok or Cancel) + if result: + import Path + p = Path.Path(dia.editor.toPlainText()) + FreeCAD.ActiveDocument.openTransaction("Edit Path") + obj.Path = p + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + +class CommandPathInspect: + + + def GetResources(self): + return {'Pixmap' : 'Path-Inspect', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Inspect","Inspect G-code"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Inspect","Inspects the G-code contents of a path")} + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + # check that the selection contains exactly what we want + selection = FreeCADGui.Selection.getSelection() + if len(selection) != 1: + FreeCAD.Console.PrintError(translate("PathInspect","Please select exactly one path object\n")) + return + if not(selection[0].isDerivedFrom("Path::Feature")): + FreeCAD.Console.PrintError(translate("PathInspect","Please select exactly one path object\n")) + return + + # if everything is ok, execute + FreeCADGui.addModule("PathScripts.PathInspect") + FreeCADGui.doCommand('PathScripts.PathInspect.show(FreeCAD.ActiveDocument.' + selection[0].Name + ')') + + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand('Path_Inspect',CommandPathInspect()) + diff --git a/src/Mod/Path/PathScripts/PathMachine.py b/src/Mod/Path/PathScripts/PathMachine.py index 15d1adc590..e69e937fa6 100644 --- a/src/Mod/Path/PathScripts/PathMachine.py +++ b/src/Mod/Path/PathScripts/PathMachine.py @@ -184,13 +184,17 @@ class _ViewProviderMachine: # this is executed when a property of the APP OBJECT changes pass - def setEdit(self,vobj,mode): #optional + def setEdit(self,vobj,mode=0): #optional # this is executed when the object is double-clicked in the tree pass - def unsetEdit(self,vobj,mode): #optional + def unsetEdit(self,vobj,mode=0): #optional # this is executed when the user cancels or terminates edit mode pass + + def doubleClicked(self,vobj): + from PathScripts import TooltableEditor + TooltableEditor.edit(vobj.Object.Name) class CommandPathMachine: def GetResources(self): diff --git a/src/Mod/Path/PathScripts/PathProject.py b/src/Mod/Path/PathScripts/PathProject.py index a542253d25..004fe6b6e1 100644 --- a/src/Mod/Path/PathScripts/PathProject.py +++ b/src/Mod/Path/PathScripts/PathProject.py @@ -66,7 +66,11 @@ class ObjectPathProject: cmds = [] for child in obj.Group: if child.isDerivedFrom("Path::Feature"): - cmds.extend(child.Path.Commands) + if obj.UsePlacements: + for c in child.Path.Commands: + cmds.append(c.transform(child.Placement)) + else: + cmds.extend(child.Path.Commands) if cmds: path = Path.Path(cmds) obj.Path = path @@ -76,16 +80,16 @@ class ViewProviderProject: def __init__(self,vobj): vobj.Proxy = self mode = 2 - vobj.setEditorMode('LineWidth',mode) - vobj.setEditorMode('MarkerColor',mode) - vobj.setEditorMode('NormalColor',mode) +# vobj.setEditorMode('LineWidth',mode) +# vobj.setEditorMode('MarkerColor',mode) +# vobj.setEditorMode('NormalColor',mode) # vobj.setEditorMode('ShowFirstRapid',mode) vobj.setEditorMode('BoundingBox',mode) vobj.setEditorMode('DisplayMode',mode) vobj.setEditorMode('Selectable',mode) vobj.setEditorMode('ShapeColor',mode) vobj.setEditorMode('Transparency',mode) - vobj.setEditorMode('Visibility',mode) +# vobj.setEditorMode('Visibility',mode) def __getstate__(self): #mandatory return None @@ -98,16 +102,16 @@ class ViewProviderProject: def onChanged(self,vobj,prop): mode = 2 - vobj.setEditorMode('LineWidth',mode) - vobj.setEditorMode('MarkerColor',mode) - vobj.setEditorMode('NormalColor',mode) +# vobj.setEditorMode('LineWidth',mode) +# vobj.setEditorMode('MarkerColor',mode) +# vobj.setEditorMode('NormalColor',mode) # vobj.setEditorMode('ShowFirstRapid',mode) vobj.setEditorMode('BoundingBox',mode) vobj.setEditorMode('DisplayMode',mode) vobj.setEditorMode('Selectable',mode) vobj.setEditorMode('ShapeColor',mode) vobj.setEditorMode('Transparency',mode) - vobj.setEditorMode('Visibility',mode) +# vobj.setEditorMode('Visibility',mode) class CommandProject: diff --git a/src/Mod/Path/PathScripts/PathSimpleCopy.py b/src/Mod/Path/PathScripts/PathSimpleCopy.py new file mode 100644 index 0000000000..adadea6350 --- /dev/null +++ b/src/Mod/Path/PathScripts/PathSimpleCopy.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2015 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Path,PathGui +from PySide import QtCore,QtGui + +"""Path SimpleCopy command""" + +# Qt tanslation handling +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig) + + +class CommandPathSimpleCopy: + + + def GetResources(self): + return {'Pixmap' : 'Path-SimpleCopy', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_SimpleCopy","Simple Copy"), + 'Accel': "P, Y", + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_SimpleCopy","Creates a non-parametric copy of another path")} + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + # check that the selection contains exactly what we want + selection = FreeCADGui.Selection.getSelection() + if len(selection) != 1: + FreeCAD.Console.PrintError(translate("Path_SimpleCopy","Please select exactly one path object\n")) + return + if not(selection[0].isDerivedFrom("Path::Feature")): + FreeCAD.Console.PrintError(translate("Path_SimpleCopy","Please select exactly one path object\n")) + return + + FreeCAD.ActiveDocument.openTransaction(translate("Path_SimpleCopy","Simple Copy")) + FreeCADGui.addModule("PathScripts.PathUtils") + FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::Feature","'+selection[0].Name+ '_copy")') + FreeCADGui.doCommand('obj.Path = FreeCAD.ActiveDocument.'+selection[0].Name+'.Path') + FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)') + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand('Path_SimpleCopy',CommandPathSimpleCopy()) diff --git a/src/Mod/Path/PathScripts/PathToolChange.py b/src/Mod/Path/PathScripts/PathToolChange.py new file mode 100644 index 0000000000..a7c14f33a4 --- /dev/null +++ b/src/Mod/Path/PathScripts/PathToolChange.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- + +#*************************************************************************** +#* * +#* Copyright (c) 2015 Yorik van Havre * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Path,PathGui +from PySide import QtCore,QtGui + +"""Path ToolChange object and FreeCAD command""" + +# Qt tanslation handling +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def translate(context, text, disambig=None): + return QtGui.QApplication.translate(context, text, disambig) + + +class ObjectToolChange: + + + def __init__(self,obj): + obj.addProperty("App::PropertyInteger","ToolNumber","Path","The tool number to be used") + obj.Proxy = self + + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + + def execute(self,obj): + path = Path.Path("M6T"+str(obj.ToolNumber)) + obj.Path = path + + +class CommandPathToolChange: + + + def GetResources(self): + return {'Pixmap' : 'Path-ToolChange', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolChange","Tool Change"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolChange","Changes the current tool")} + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + FreeCAD.ActiveDocument.openTransaction("Create Tool Change") + FreeCADGui.addModule("PathScripts.PathToolChange") + FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","ToolChange")') + FreeCADGui.doCommand('PathScripts.PathToolChange.ObjectToolChange(obj)') + FreeCADGui.doCommand('obj.ViewObject.Proxy = 0') + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + +if FreeCAD.GuiUp: + # register the FreeCAD command + FreeCADGui.addCommand('Path_ToolChange',CommandPathToolChange()) diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 90e5de3c60..0e5464da35 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -359,17 +359,17 @@ def findMachine(): return o def addToProject(obj): - """Adds a path obj to this document, if no PathParoject exists it's created on the fly""" + """Adds a path obj to this document, if no PathParoject exists it's created on the fly""" + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") + if p.GetBool("pathAutoProject",True): project = findProj() - - if project == None: + if not project: project = PathProject.CommandProject.Create() - g = project.Group g.append(obj) project.Group = g - return project + return None def getLastZ(obj): diff --git a/src/Mod/Points/App/AppPoints.cpp b/src/Mod/Points/App/AppPoints.cpp index 7f353f2c33..fa79055469 100644 --- a/src/Mod/Points/App/AppPoints.cpp +++ b/src/Mod/Points/App/AppPoints.cpp @@ -35,22 +35,18 @@ #include "PropertyPointKernel.h" #include "ViewFeature.h" - -/* registration table */ - -extern struct PyMethodDef Points_Import_methods[]; - - +namespace Points { + extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void PointsExport initPoints() +PyMODINIT_FUNC initPoints() { - PyObject* pointsModule = Py_InitModule("Points", Points_Import_methods); /* mod name, table ptr */ + PyObject* pointsModule = Points::initModule(); Base::Console().Log("Loading Points module... done\n"); // add python types - Base::Interpreter().addType(&Points::PointsPy ::Type,pointsModule,"Points"); + Base::Interpreter().addType(&Points::PointsPy::Type, pointsModule, "Points"); // add properties Points::PropertyGreyValue ::init(); @@ -65,5 +61,3 @@ void PointsExport initPoints() Points::FeaturePython ::init(); Points::ViewFeature ::init(); } - -} // extern "C" diff --git a/src/Mod/Points/App/AppPointsPy.cpp b/src/Mod/Points/App/AppPointsPy.cpp index d79aca74bb..5a1ef28eb8 100644 --- a/src/Mod/Points/App/AppPointsPy.cpp +++ b/src/Mod/Points/App/AppPointsPy.cpp @@ -32,6 +32,9 @@ # include #endif +#include +#include + #include #include #include @@ -47,203 +50,224 @@ #include "PointsFeature.h" #include "Properties.h" -using namespace Points; - -/* module functions */ -static PyObject * -open(PyObject *self, PyObject *args) +namespace Points { +class Module : public Py::ExtensionModule { - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("Points") + { + add_varargs_method("open",&Module::open + ); + add_varargs_method("insert",&Module::insert + ); + add_varargs_method("show",&Module::show + ); + initialize("This module is the Points module."); // register with Python + } - PY_TRY { - Base::Console().Log("Open in Points with %s",EncodedName.c_str()); - Base::FileInfo file(EncodedName.c_str()); + virtual ~Module() {} - // extract ending - if (file.extension() == "") - Py_Error(Base::BaseExceptionFreeCADError,"no file ending"); +private: + 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); - if (file.hasExtension("asc")) { - // create new document and add Import feature - App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); - Points::Feature *pcFeature = (Points::Feature *)pcDoc->addObject("Points::Feature", file.fileNamePure().c_str()); - Points::PointKernel pkTemp; - pkTemp.load(EncodedName.c_str()); - pcFeature->Points.setValue( pkTemp ); + try { + Base::Console().Log("Open in Points with %s",EncodedName.c_str()); + Base::FileInfo file(EncodedName.c_str()); - } + // extract ending + if (file.extension().empty()) + throw Py::RuntimeError("No file extension"); + + if (file.hasExtension("asc")) { + // create new document and add Import feature + App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); + Points::Feature *pcFeature = (Points::Feature *)pcDoc->addObject("Points::Feature", file.fileNamePure().c_str()); + Points::PointKernel pkTemp; + pkTemp.load(EncodedName.c_str()); + pcFeature->Points.setValue( pkTemp ); + + } #ifdef HAVE_PCL_IO - else if (file.hasExtension("ply")) { - PlyReader reader; - reader.read(EncodedName); + else if (file.hasExtension("ply")) { + PlyReader reader; + reader.read(EncodedName); - App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); - if (reader.hasProperties()) { - Points::FeatureCustom *pcFeature = new Points::FeatureCustom(); - pcFeature->Points.setValue(reader.getPoints()); - // add gray values - if (reader.hasIntensities()) { - Points::PropertyGreyValueList* prop = static_cast - (pcFeature->addDynamicProperty("Points::PropertyGreyValueList", "Intensity")); - if (prop) { - prop->setValues(reader.getIntensities()); + App::Document *pcDoc = App::GetApplication().newDocument("Unnamed"); + if (reader.hasProperties()) { + Points::FeatureCustom *pcFeature = new Points::FeatureCustom(); + pcFeature->Points.setValue(reader.getPoints()); + // add gray values + if (reader.hasIntensities()) { + Points::PropertyGreyValueList* prop = static_cast + (pcFeature->addDynamicProperty("Points::PropertyGreyValueList", "Intensity")); + if (prop) { + prop->setValues(reader.getIntensities()); + } } - } - // add colors - if (reader.hasColors()) { - App::PropertyColorList* prop = static_cast - (pcFeature->addDynamicProperty("App::PropertyColorList", "Color")); - if (prop) { - prop->setValues(reader.getColors()); + // add colors + if (reader.hasColors()) { + App::PropertyColorList* prop = static_cast + (pcFeature->addDynamicProperty("App::PropertyColorList", "Color")); + if (prop) { + prop->setValues(reader.getColors()); + } } - } - // add normals - if (reader.hasNormals()) { - Points::PropertyNormalList* prop = static_cast - (pcFeature->addDynamicProperty("Points::PropertyNormalList", "Normal")); - if (prop) { - prop->setValues(reader.getNormals()); + // add normals + if (reader.hasNormals()) { + Points::PropertyNormalList* prop = static_cast + (pcFeature->addDynamicProperty("Points::PropertyNormalList", "Normal")); + if (prop) { + prop->setValues(reader.getNormals()); + } } - } - // delayed adding of the points feature - pcDoc->addObject(pcFeature, file.fileNamePure().c_str()); - pcDoc->recomputeFeature(pcFeature); + // delayed adding of the points feature + pcDoc->addObject(pcFeature, file.fileNamePure().c_str()); + pcDoc->recomputeFeature(pcFeature); + } + else { + Points::Feature *pcFeature = static_cast + (pcDoc->addObject("Points::Feature", file.fileNamePure().c_str())); + pcFeature->Points.setValue(reader.getPoints()); + pcDoc->recomputeFeature(pcFeature); + } } - else { - Points::Feature *pcFeature = static_cast - (pcDoc->addObject("Points::Feature", file.fileNamePure().c_str())); - pcFeature->Points.setValue(reader.getPoints()); - pcDoc->recomputeFeature(pcFeature); - } - } #endif - else { - Py_Error(Base::BaseExceptionFreeCADError,"unknown file ending"); - } - } PY_CATCH; - - Py_Return; -} - -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("Import in Points with %s",EncodedName.c_str()); - Base::FileInfo file(EncodedName.c_str()); - - // extract ending - if (file.extension() == "") - Py_Error(Base::BaseExceptionFreeCADError,"no file ending"); - - if (file.hasExtension("asc")) { - // add Import feature - App::Document *pcDoc = App::GetApplication().getDocument(DocName); - if (!pcDoc) { - pcDoc = App::GetApplication().newDocument(DocName); + else { + throw Py::RuntimeError("Unsupported file extension"); } - - Points::Feature *pcFeature = (Points::Feature *)pcDoc->addObject("Points::Feature", file.fileNamePure().c_str()); - Points::PointKernel pkTemp; - pkTemp.load(EncodedName.c_str()); - pcFeature->Points.setValue( pkTemp ); } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + 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); + + try { + Base::Console().Log("Import in Points with %s",EncodedName.c_str()); + Base::FileInfo file(EncodedName.c_str()); + + // extract ending + if (file.extension().empty()) + throw Py::RuntimeError("No file extension"); + + if (file.hasExtension("asc")) { + // add Import feature + App::Document *pcDoc = App::GetApplication().getDocument(DocName); + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument(DocName); + } + + Points::Feature *pcFeature = (Points::Feature *)pcDoc->addObject("Points::Feature", file.fileNamePure().c_str()); + Points::PointKernel pkTemp; + pkTemp.load(EncodedName.c_str()); + pcFeature->Points.setValue( pkTemp ); + } #ifdef HAVE_PCL_IO - else if (file.hasExtension("ply")) { - App::Document *pcDoc = App::GetApplication().getDocument(DocName); - if (!pcDoc) { - pcDoc = App::GetApplication().newDocument(DocName); - } - - PlyReader reader; - reader.read(EncodedName); - - if (reader.hasProperties()) { - Points::FeatureCustom *pcFeature = new Points::FeatureCustom(); - pcFeature->Points.setValue(reader.getPoints()); - // add gray values - if (reader.hasIntensities()) { - Points::PropertyGreyValueList* prop = static_cast - (pcFeature->addDynamicProperty("Points::PropertyGreyValueList", "Intensity")); - if (prop) { - prop->setValues(reader.getIntensities()); - } - } - // add colors - if (reader.hasColors()) { - App::PropertyColorList* prop = static_cast - (pcFeature->addDynamicProperty("App::PropertyColorList", "Color")); - if (prop) { - prop->setValues(reader.getColors()); - } - } - // add normals - if (reader.hasNormals()) { - Points::PropertyNormalList* prop = static_cast - (pcFeature->addDynamicProperty("Points::PropertyNormalList", "Normal")); - if (prop) { - prop->setValues(reader.getNormals()); - } + else if (file.hasExtension("ply")) { + App::Document *pcDoc = App::GetApplication().getDocument(DocName); + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument(DocName); } - // delayed adding of the points feature - pcDoc->addObject(pcFeature, file.fileNamePure().c_str()); - pcDoc->recomputeFeature(pcFeature); + PlyReader reader; + reader.read(EncodedName); + + if (reader.hasProperties()) { + Points::FeatureCustom *pcFeature = new Points::FeatureCustom(); + pcFeature->Points.setValue(reader.getPoints()); + // add gray values + if (reader.hasIntensities()) { + Points::PropertyGreyValueList* prop = static_cast + (pcFeature->addDynamicProperty("Points::PropertyGreyValueList", "Intensity")); + if (prop) { + prop->setValues(reader.getIntensities()); + } + } + // add colors + if (reader.hasColors()) { + App::PropertyColorList* prop = static_cast + (pcFeature->addDynamicProperty("App::PropertyColorList", "Color")); + if (prop) { + prop->setValues(reader.getColors()); + } + } + // add normals + if (reader.hasNormals()) { + Points::PropertyNormalList* prop = static_cast + (pcFeature->addDynamicProperty("Points::PropertyNormalList", "Normal")); + if (prop) { + prop->setValues(reader.getNormals()); + } + } + + // delayed adding of the points feature + pcDoc->addObject(pcFeature, file.fileNamePure().c_str()); + pcDoc->recomputeFeature(pcFeature); + } + else { + Points::Feature *pcFeature = static_cast + (pcDoc->addObject("Points::Feature", file.fileNamePure().c_str())); + pcFeature->Points.setValue(reader.getPoints()); + pcDoc->recomputeFeature(pcFeature); + } } - else { - Points::Feature *pcFeature = static_cast - (pcDoc->addObject("Points::Feature", file.fileNamePure().c_str())); - pcFeature->Points.setValue(reader.getPoints()); - pcDoc->recomputeFeature(pcFeature); - } - } #endif - else { - Py_Error(Base::BaseExceptionFreeCADError,"unknown file ending"); + else { + throw Py::RuntimeError("Unsupported file extension"); + } + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); } - } PY_CATCH; - Py_Return; -} + return Py::None(); + } -static PyObject * -show(PyObject *self, PyObject *args) -{ - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O!", &(PointsPy::Type), &pcObj)) // convert args: Python->C - return NULL; // NULL triggers exception + Py::Object show(const Py::Tuple& args) + { + PyObject *pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O!", &(PointsPy::Type), &pcObj)) + throw Py::Exception(); - PY_TRY { - App::Document *pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(); - PointsPy* pPoints = static_cast(pcObj); - Points::Feature *pcFeature = (Points::Feature *)pcDoc->addObject("Points::Feature", "Points"); - // copy the data - //TopoShape* shape = new MeshObject(*pShape->getTopoShapeObjectPtr()); - pcFeature->Points.setValue(*(pPoints->getPointKernelPtr())); - //pcDoc->recompute(); - } PY_CATCH; + try { + App::Document *pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(); + PointsPy* pPoints = static_cast(pcObj); + Points::Feature *pcFeature = (Points::Feature *)pcDoc->addObject("Points::Feature", "Points"); + // copy the data + //TopoShape* shape = new MeshObject(*pShape->getTopoShapeObjectPtr()); + pcFeature->Points.setValue(*(pPoints->getPointKernelPtr())); + //pcDoc->recompute(); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } - Py_Return; -} - -// registration table -struct PyMethodDef Points_Import_methods[] = { - {"open", open, 1}, /* method name, C func ptr, always-tuple */ - {"insert",insert, 1}, - {"show",show, 1}, - {NULL, NULL} /* end of table marker */ + return Py::None(); + } }; + +PyObject* initModule() +{ + return (new Module())->module().ptr(); +} + +} // namespace Points diff --git a/src/Mod/Points/App/Properties.cpp b/src/Mod/Points/App/Properties.cpp index 4aecac874b..1c94f60d8d 100644 --- a/src/Mod/Points/App/Properties.cpp +++ b/src/Mod/Points/App/Properties.cpp @@ -364,7 +364,7 @@ unsigned int PropertyNormalList::getMemSize (void) const return static_cast(_lValueList.size() * sizeof(Base::Vector3f)); } -void PropertyNormalList::transform(const Base::Matrix4D &mat) +void PropertyNormalList::transformGeometry(const Base::Matrix4D &mat) { // A normal vector is only a direction with unit length, so we only need to rotate it // (no translations or scaling) @@ -386,10 +386,14 @@ void PropertyNormalList::transform(const Base::Matrix4D &mat) } } + aboutToSetValue(); + // Rotate the normal vectors for (int ii=0; ii& uIndices ) @@ -489,7 +493,7 @@ std::vector PropertyCurvatureList::getCurvature( int mode ) const return fValues; } -void PropertyCurvatureList::transform(const Base::Matrix4D &mat) +void PropertyCurvatureList::transformGeometry(const Base::Matrix4D &mat) { // The principal direction is only a vector with unit length, so we only need to rotate it // (no translations or scaling) @@ -511,6 +515,8 @@ void PropertyCurvatureList::transform(const Base::Matrix4D &mat) } } + aboutToSetValue(); + // Rotate the principal directions for (int ii=0; ii& uIndices ) diff --git a/src/Mod/Points/App/Properties.h b/src/Mod/Points/App/Properties.h index 584515bb35..6f2c6c68ec 100644 --- a/src/Mod/Points/App/Properties.h +++ b/src/Mod/Points/App/Properties.h @@ -71,13 +71,19 @@ public: void setValue(float); /// index operator - float operator[] (const int idx) const {return _lValueList.operator[] (idx);} - - void set1Value (const int idx, float value){_lValueList.operator[] (idx) = value;} + float operator[] (const int idx) const { + return _lValueList[idx]; + } + + void set1Value (const int idx, float value) { + _lValueList[idx] = value; + } void setValues (const std::vector& values); - const std::vector &getValues(void) const{return _lValueList;} - + const std::vector &getValues(void) const { + return _lValueList; + } + virtual PyObject *getPyObject(void); virtual void setPyObject(PyObject *); @@ -115,11 +121,11 @@ public: void setValue(float x, float y, float z); const Base::Vector3f& operator[] (const int idx) const { - return _lValueList.operator[] (idx); + return _lValueList[idx]; } void set1Value (const int idx, const Base::Vector3f& value) { - _lValueList.operator[] (idx) = value; + _lValueList[idx] = value; } void setValues (const std::vector& values); @@ -144,7 +150,7 @@ public: /** @name Modify */ //@{ - void transform(const Base::Matrix4D &rclMat); + void transformGeometry(const Base::Matrix4D &rclMat); void removeIndices( const std::vector& ); //@} @@ -178,16 +184,26 @@ public: PropertyCurvatureList(); ~PropertyCurvatureList(); - void setSize(int newSize){_lValueList.resize(newSize);} - int getSize(void) const {return _lValueList.size();} + void setSize(int newSize) { + _lValueList.resize(newSize); + } + int getSize(void) const { + return _lValueList.size(); + } void setValue(const CurvatureInfo&); void setValues(const std::vector&); std::vector getCurvature( int tMode) const; /// index operator - const CurvatureInfo& operator[] (const int idx) const {return _lValueList.operator[] (idx);} - void set1Value (const int idx, const CurvatureInfo& value){_lValueList.operator[] (idx) = value;} - const std::vector &getValues(void) const{return _lValueList;} + const CurvatureInfo& operator[] (const int idx) const { + return _lValueList[idx]; + } + void set1Value (const int idx, const CurvatureInfo& value) { + _lValueList[idx] = value; + } + const std::vector &getValues(void) const { + return _lValueList; + } /** @name Save/restore */ //@{ @@ -209,7 +225,7 @@ public: /** @name Modify */ //@{ - void transform(const Base::Matrix4D &rclMat); + void transformGeometry(const Base::Matrix4D &rclMat); void removeIndices( const std::vector& ); //@} diff --git a/src/Mod/Points/Gui/AppPointsGui.cpp b/src/Mod/Points/Gui/AppPointsGui.cpp index b54d6f26cf..ed79d26f0e 100644 --- a/src/Mod/Points/Gui/AppPointsGui.cpp +++ b/src/Mod/Points/Gui/AppPointsGui.cpp @@ -25,6 +25,9 @@ #ifndef _PreComp_ #endif +#include +#include + #include "ViewProvider.h" #include "Workbench.h" @@ -44,15 +47,25 @@ void loadPointsResource() Gui::Translator::instance()->refresh(); } +namespace PointsGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("PointsGui") + { + initialize("This module is the PointsGui module."); // register with Python + } -/* registration table */ -static struct PyMethodDef PointsGui_methods[] = { - {NULL, NULL} /* end of table marker */ + virtual ~Module() {} + +private: }; +} // namespace PointsGui + + /* Python entry */ -extern "C" { -void PointsGuiExport initPointsGui() +PyMODINIT_FUNC initPointsGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -69,7 +82,7 @@ void PointsGuiExport initPointsGui() } Base::Console().Log("Loading GUI of Points module... done\n"); - (void) Py_InitModule("PointsGui", PointsGui_methods); /* mod name, table ptr */ + (void)new PointsGui::Module(); // instantiating the commands CreatePointsCommands(); @@ -84,5 +97,3 @@ void PointsGuiExport initPointsGui() // add resources and reloads the translators loadPointsResource(); } - -} // extern "C" diff --git a/src/Mod/Raytracing/App/AppRaytracing.cpp b/src/Mod/Raytracing/App/AppRaytracing.cpp index 24d9ca6eef..db669ec9a5 100644 --- a/src/Mod/Raytracing/App/AppRaytracing.cpp +++ b/src/Mod/Raytracing/App/AppRaytracing.cpp @@ -35,11 +35,12 @@ #include "LuxFeature.h" #include "LuxProject.h" -extern struct PyMethodDef Raytracing_methods[]; +namespace Raytracing { + extern PyObject* initModule(); +} -extern "C" { -void AppRaytracingExport initRaytracing() +PyMODINIT_FUNC initRaytracing() { // load dependent module try { @@ -50,16 +51,13 @@ void AppRaytracingExport initRaytracing() return; } - Raytracing::RaySegment ::init(); - Raytracing::RayFeature ::init(); - Raytracing::RayProject ::init(); + Raytracing::RaySegment ::init(); + Raytracing::RayFeature ::init(); + Raytracing::RayProject ::init(); Raytracing::LuxFeature ::init(); Raytracing::LuxProject ::init(); - (void) Py_InitModule("Raytracing", Raytracing_methods); /* mod name, table ptr */ + (void) Raytracing::initModule(); Base::Console().Log("Loading Raytracing module... done\n"); - } - -} // extern "C" { diff --git a/src/Mod/Raytracing/App/AppRaytracingPy.cpp b/src/Mod/Raytracing/App/AppRaytracingPy.cpp index e043300d28..cd702a0348 100644 --- a/src/Mod/Raytracing/App/AppRaytracingPy.cpp +++ b/src/Mod/Raytracing/App/AppRaytracingPy.cpp @@ -27,6 +27,9 @@ #include +#include +#include + #include #include "PovTools.h" #include "LuxTools.h" @@ -37,217 +40,211 @@ #include #include -using namespace Raytracing; - -/// write empty project file -static PyObject * -writeProjectFile(PyObject *self, PyObject *args) +namespace Raytracing { +class Module : public Py::ExtensionModule { - char *fromPython; - if (! PyArg_ParseTuple(args, "(s)", &fromPython)) - return NULL; - - std::ofstream fout; - if(fromPython) - fout.open(fromPython); - else - fout.open("FreeCAD.pov"); - - fout << FreeCAD ; - fout.close(); - - Py_Return; -} - -/// write project file -static PyObject * -getProjectFile(PyObject *self, PyObject *args) -{ - return Py_BuildValue("s", FreeCAD); -} - -/// get part file as string -static PyObject * -getPartAsPovray(PyObject *self, PyObject *args) -{ - float r=0.5,g=0.5,b=0.5; - PyObject *ShapeObject; - const char *PartName; - if (! PyArg_ParseTuple(args, "sO!|fff",&PartName, - &(Part::TopoShapePy::Type), &ShapeObject,&r,&g,&b)) - return NULL; - - std::stringstream out; - TopoDS_Shape &aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; - - PovTools::writeShape(out,PartName,aShape,(float)0.1); - // This must not be done in PovTools::writeShape! - out << "// instance to render" << endl - << "object {" << PartName << endl - << " texture {" << endl - << " pigment {color rgb <"<}" << endl - << " finish {StdFinish } //definition on top of the project" << endl - << " }" << endl - << "}" << endl ; - return Py::new_reference_to(Py::String(out.str())); -} - -/// get part as lux string -static PyObject * -getPartAsLux(PyObject *self, PyObject *args) -{ - float r=0.5,g=0.5,b=0.5; - PyObject *ShapeObject; - const char *PartName; - if (! PyArg_ParseTuple(args, "sO!|fff",&PartName, - &(Part::TopoShapePy::Type), &ShapeObject,&r,&g,&b)) - return NULL; - - std::stringstream out; - TopoDS_Shape &aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; - - // write a material entry - // This must not be done in PovTools::writeShape! - out << "MakeNamedMaterial \"FreeCADMaterial_" << PartName << "\"" << endl; - out << " \"color Kd\" [" << r << " " << g << " " << b << "]" << endl; - out << " \"float sigma\" [0.000000000000000]" << endl; - out << " \"string type\" [\"matte\"]" << endl << endl; - - LuxTools::writeShape(out,PartName,aShape,(float)0.1); - - return Py::new_reference_to(Py::String(out.str())); -} - -/// write part file -static PyObject * -writePartFile(PyObject *self, PyObject *args) -{ - PyObject *ShapeObject; - const char *FileName,*PartName; - if (! PyArg_ParseTuple(args, "ssO!",&FileName,&PartName, - &(Part::TopoShapePy::Type), &ShapeObject)) - return NULL; - - TopoDS_Shape &aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; - - PovTools::writeShape(FileName,PartName,aShape,(float)0.1); - - Py_Return; -} - -/// write part file -static PyObject * -writeDataFile(PyObject *self, PyObject *args) -{ - PyObject *dataObject; - const char *FileName,*PartName; - if (! PyArg_ParseTuple(args, "ssO!",&FileName,&PartName, - &(Data::ComplexGeoDataPy::Type), &dataObject)) - return 0; - - const Data::ComplexGeoData* aData = static_cast - (dataObject)->getComplexGeoDataPtr(); - - PovTools::writeData(FileName,PartName,aData,0.1f); - - Py_Return; -} - -/// write part file as CSV -static PyObject * -writePartFileCSV(PyObject *self, PyObject *args) -{ - PyObject *ShapeObject; - const char *FileName; - float Acur,Length; - if (! PyArg_ParseTuple(args, "O!sff",&(Part::TopoShapePy::Type), - &ShapeObject,&FileName,&Acur,&Length)) - return NULL; - - TopoDS_Shape aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; - PovTools::writeShapeCSV(FileName,aShape,Acur,Length); - Py_Return; -} - -/// write project file -static PyObject * -writeCameraFile(PyObject *self, PyObject *args) -{ - PyObject *Arg[4]; - const char *FileName; - double vecs[4][3]; - if (! PyArg_ParseTuple(args, "sO!O!O!O!",&FileName,&PyTuple_Type, - &Arg[0],&PyTuple_Type, &Arg[1],&PyTuple_Type, &Arg[2],&PyTuple_Type, &Arg[3])) - return NULL; - - // go throug the Tuple of Tupls - for(int i=0;i<4;i++) { - // check the right size of the Tuple of floats - if(PyTuple_GET_SIZE(Arg[i]) != 3) - Py_Error(Base::BaseExceptionFreeCADError,"Wrong parameter format, four Tuple of three floats needed!"); - - // go through the Tuple of floats - for(int l=0;l<3;l++) { - PyObject* temp = PyTuple_GetItem(Arg[i],l); - // check Type - if (PyFloat_Check(temp)) - vecs[i][l] = PyFloat_AsDouble(temp); - else if (PyLong_Check(temp)) - vecs[i][l] = (double) PyLong_AsLong(temp); - else if (PyInt_Check(temp)) - vecs[i][l] = (double) PyInt_AsLong(temp); - else - Py_Error(Base::BaseExceptionFreeCADError,"Wrong parameter format, four Tuple of three floats needed!"); - } +public: + Module() : Py::ExtensionModule("Raytracing") + { + add_varargs_method("writeProjectFile",&Module::writeProjectFile + ); + add_varargs_method("getProjectFile",&Module::getProjectFile + ); + add_varargs_method("getPartAsPovray",&Module::getPartAsPovray + ); + add_varargs_method("getPartAsLux",&Module::getPartAsLux + ); + add_varargs_method("writePartFile",&Module::writePartFile + ); + add_varargs_method("writeDataFile",&Module::writeDataFile + ); + add_varargs_method("writePartFileCSV",&Module::writePartFileCSV + ); + add_varargs_method("writeCameraFile",&Module::writeCameraFile + ); + add_varargs_method("copyResource",&Module::copyResource + ); + initialize("This module is the Raytracing module."); // register with Python } - // call the write method of PovTools.... - PovTools::writeCamera(FileName,CamDef(gp_Vec(vecs[0][0],vecs[0][1],vecs[0][2]), - gp_Vec(vecs[1][0],vecs[1][1],vecs[1][2]), - gp_Vec(vecs[2][0],vecs[2][1],vecs[2][2]), - gp_Vec(vecs[3][0],vecs[3][1],vecs[3][2]))); + virtual ~Module() {} - Py_Return; -} +private: + Py::Object writeProjectFile(const Py::Tuple& args) + { + char *fromPython; + if (! PyArg_ParseTuple(args.ptr(), "(s)", &fromPython)) + throw Py::Exception(); -/// write project file -static PyObject * -copyResource(PyObject *self, PyObject *args) -{ - const char *FileName,*DestDir; - if (! PyArg_ParseTuple(args, "ss",&FileName,&DestDir)) - return NULL; + std::ofstream fout; + if (fromPython) + fout.open(fromPython); + else + fout.open("FreeCAD.pov"); - std::string resName = App::GetApplication().getHomePath(); - resName += "Mod"; - resName += PATHSEP ; - resName += "Raytracing"; - resName += PATHSEP ; - resName += "resources"; - resName += PATHSEP; - resName += FileName; + fout << FreeCAD ; + fout.close(); + return Py::None(); + } + Py::Object getProjectFile(const Py::Tuple& /*args*/) + { + return Py::String(FreeCAD); + } + Py::Object getPartAsPovray(const Py::Tuple& args) + { + float r=0.5,g=0.5,b=0.5; + PyObject *ShapeObject; + const char *PartName; + if (! PyArg_ParseTuple(args.ptr(), "sO!|fff",&PartName, + &(Part::TopoShapePy::Type), &ShapeObject,&r,&g,&b)) + throw Py::Exception(); - Base::Console().Warning("Using fileName = %s\nRaytracer scene file not generated " - "because function is not implemented yet.\nYou can copy " - "the standard scene file FreeCAD.pov to your raytracing " - "directory to render the scene.\n",resName.c_str()); + std::stringstream out; + TopoDS_Shape &aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; + + PovTools::writeShape(out,PartName,aShape,(float)0.1); + // This must not be done in PovTools::writeShape! + out << "// instance to render" << endl + << "object {" << PartName << endl + << " texture {" << endl + << " pigment {color rgb <"<}" << endl + << " finish {StdFinish } //definition on top of the project" << endl + << " }" << endl + << "}" << endl ; + return Py::String(out.str()); + } + Py::Object getPartAsLux(const Py::Tuple& args) + { + float r=0.5,g=0.5,b=0.5; + PyObject *ShapeObject; + const char *PartName; + if (! PyArg_ParseTuple(args.ptr(), "sO!|fff",&PartName, + &(Part::TopoShapePy::Type), &ShapeObject,&r,&g,&b)) + throw Py::Exception(); + + std::stringstream out; + TopoDS_Shape &aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; + + // write a material entry + // This must not be done in PovTools::writeShape! + out << "MakeNamedMaterial \"FreeCADMaterial_" << PartName << "\"" << endl; + out << " \"color Kd\" [" << r << " " << g << " " << b << "]" << endl; + out << " \"float sigma\" [0.000000000000000]" << endl; + out << " \"string type\" [\"matte\"]" << endl << endl; + + LuxTools::writeShape(out,PartName,aShape,(float)0.1); + return Py::String(out.str()); + } + Py::Object writePartFile(const Py::Tuple& args) + { + PyObject *ShapeObject; + const char *FileName,*PartName; + if (! PyArg_ParseTuple(args.ptr(), "ssO!",&FileName,&PartName, + &(Part::TopoShapePy::Type), &ShapeObject)) + throw Py::Exception(); + + TopoDS_Shape &aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; + + PovTools::writeShape(FileName,PartName,aShape,(float)0.1); + + return Py::None(); + } + Py::Object writeDataFile(const Py::Tuple& args) + { + PyObject *dataObject; + const char *FileName,*PartName; + if (! PyArg_ParseTuple(args.ptr(), "ssO!",&FileName,&PartName, + &(Data::ComplexGeoDataPy::Type), &dataObject)) + throw Py::Exception(); + + const Data::ComplexGeoData* aData = static_cast + (dataObject)->getComplexGeoDataPtr(); + + PovTools::writeData(FileName,PartName,aData,0.1f); + + return Py::None(); + } + Py::Object writePartFileCSV(const Py::Tuple& args) + { + PyObject *ShapeObject; + const char *FileName; + float Acur,Length; + if (!PyArg_ParseTuple(args.ptr(), "O!sff",&(Part::TopoShapePy::Type), + &ShapeObject,&FileName,&Acur,&Length)) + throw Py::Exception(); + + TopoDS_Shape aShape = static_cast(ShapeObject)->getTopoShapePtr()->_Shape; + PovTools::writeShapeCSV(FileName,aShape,Acur,Length); + return Py::None(); + } + Py::Object writeCameraFile(const Py::Tuple& args) + { + PyObject *Arg[4]; + const char *FileName; + double vecs[4][3]; + if (!PyArg_ParseTuple(args.ptr(), "sO!O!O!O!",&FileName,&PyTuple_Type, + &Arg[0],&PyTuple_Type, &Arg[1],&PyTuple_Type, &Arg[2],&PyTuple_Type, &Arg[3])) + throw Py::Exception(); + + // go throug the Tuple of Tuples + for (int i=0;i<4;i++) { + // check the right size of the Tuple of floats + if (PyTuple_GET_SIZE(Arg[i]) != 3) + throw Py::ValueError("Wrong parameter format, four Tuple of three floats needed!"); + + // go through the Tuple of floats + for (int l=0;l<3;l++) { + PyObject* temp = PyTuple_GetItem(Arg[i],l); + // check Type + if (PyFloat_Check(temp)) + vecs[i][l] = PyFloat_AsDouble(temp); + else if (PyLong_Check(temp)) + vecs[i][l] = (double) PyLong_AsLong(temp); + else if (PyInt_Check(temp)) + vecs[i][l] = (double) PyInt_AsLong(temp); + else + throw Py::ValueError("Wrong parameter format, four Tuple of three floats needed!"); + } + } + + // call the write method of PovTools.... + PovTools::writeCamera(FileName,CamDef(gp_Vec(vecs[0][0],vecs[0][1],vecs[0][2]), + gp_Vec(vecs[1][0],vecs[1][1],vecs[1][2]), + gp_Vec(vecs[2][0],vecs[2][1],vecs[2][2]), + gp_Vec(vecs[3][0],vecs[3][1],vecs[3][2]))); + + return Py::None(); + } + Py::Object copyResource(const Py::Tuple& args) + { + const char *FileName,*DestDir; + if (! PyArg_ParseTuple(args.ptr(), "ss",&FileName,&DestDir)) + throw Py::Exception(); + + std::string resName = App::GetApplication().getHomePath(); + resName += "Mod"; + resName += PATHSEP ; + resName += "Raytracing"; + resName += PATHSEP ; + resName += "resources"; + resName += PATHSEP; + resName += FileName; + + Base::Console().Warning("Using fileName = %s\nRaytracer scene file not generated " + "because function is not implemented yet.\nYou can copy " + "the standard scene file FreeCAD.pov to your raytracing " + "directory to render the scene.\n",resName.c_str()); // This command should create the povray scene file, but does currently do nothing. - Py_Return; + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef Raytracing_methods[] = { - {"writeProjectFile", writeProjectFile, 1}, - {"getProjectFile", getProjectFile , 1}, - {"writePartFile", writePartFile , 1}, - {"writePartFileCSV", writePartFileCSV, 1}, - {"getPartAsPovray", getPartAsPovray , 1}, - {"getPartAsLux", getPartAsLux , 1}, - {"writeDataFile", writeDataFile , 1}, - {"writeCameraFile", writeCameraFile , 1}, - {"copyResource", copyResource , 1}, - {NULL, NULL} -}; +} // namespace Raytracing diff --git a/src/Mod/Raytracing/Gui/AppRaytracingGui.cpp b/src/Mod/Raytracing/Gui/AppRaytracingGui.cpp index 296d6b9ffc..5254dc73dd 100644 --- a/src/Mod/Raytracing/Gui/AppRaytracingGui.cpp +++ b/src/Mod/Raytracing/Gui/AppRaytracingGui.cpp @@ -46,11 +46,12 @@ void loadRaytracingResource() Gui::Translator::instance()->refresh(); } -extern struct PyMethodDef RaytracingGui_methods[]; +namespace RaytracingGui { + PyObject* initModule(); +} -extern "C" { -void AppRaytracingGuiExport initRaytracingGui() +PyMODINIT_FUNC initRaytracingGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -64,7 +65,7 @@ void AppRaytracingGuiExport initRaytracingGui() PyErr_SetString(PyExc_ImportError, e.what()); return; } - (void) Py_InitModule("RaytracingGui", RaytracingGui_methods); /* mod name, table ptr */ + (void) RaytracingGui::initModule(); Base::Console().Log("Loading GUI of Raytracing module... done\n"); // instantiating the commands @@ -79,5 +80,3 @@ void AppRaytracingGuiExport initRaytracingGui() // add resources and reloads the translators loadRaytracingResource(); } - -} // extern "C" { diff --git a/src/Mod/Raytracing/Gui/AppRaytracingGuiPy.cpp b/src/Mod/Raytracing/Gui/AppRaytracingGuiPy.cpp index abeabcdace..68bb263293 100644 --- a/src/Mod/Raytracing/Gui/AppRaytracingGuiPy.cpp +++ b/src/Mod/Raytracing/Gui/AppRaytracingGuiPy.cpp @@ -32,6 +32,9 @@ # include #endif +#include +#include + #include #include #include @@ -45,196 +48,208 @@ #include #include "PovrayHighlighter.h" -using namespace RaytracingGui; -using namespace Raytracing; - -/// open pov file -static PyObject * -open(PyObject *self, PyObject *args) +namespace RaytracingGui { +class Module : public Py::ExtensionModule { - // only used to open Povray files - char* Name; - const char* DocName; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - PY_TRY { - QString fileName = QString::fromUtf8(EncodedName.c_str()); - QFileInfo fi; - fi.setFile(fileName); - QString ext = fi.completeSuffix().toLower(); - QList views = Gui::getMainWindow()->findChildren(); - for (QList::Iterator it = views.begin(); it != views.end(); ++it) { - if ((*it)->fileName() == fileName) { - (*it)->setFocus(); - Py_Return; +public: + Module() : Py::ExtensionModule("RaytracingGui") + { + add_varargs_method("open",&Module::open, + "open(string) -- Create a new text document and load the file into the document." + ); + add_varargs_method("insert",&Module::open, + "insert(string,string) -- Create a new text document and load the file into the document." + ); + add_varargs_method("povViewCamera",&Module::povViewCamera, + "string povViewCamera() -- returns the povray camera definition of the active 3D view." + ); + add_varargs_method("luxViewCamera",&Module::luxViewCamera, + "string luxViewCamera() -- returns the luxrender camera definition of the active 3D view." + ); + initialize("This module is the RaytracingGui module."); // register with Python + } + + virtual ~Module() {} + +private: + Py::Object open(const Py::Tuple& args) + { + // only used to open Povray files + char* Name; + const char* DocName; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + throw Py::Exception(); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + try { + QString fileName = QString::fromUtf8(EncodedName.c_str()); + QFileInfo fi; + fi.setFile(fileName); + QString ext = fi.completeSuffix().toLower(); + QList views = Gui::getMainWindow()->findChildren(); + for (QList::Iterator it = views.begin(); it != views.end(); ++it) { + if ((*it)->fileName() == fileName) { + (*it)->setFocus(); + return Py::None(); + } + } + + if (ext == QLatin1String("pov") || ext == QLatin1String("inc")) { + Gui::TextEditor* editor = new Gui::TextEditor(); + editor->setSyntaxHighlighter(new PovrayHighlighter(editor)); + Gui::EditorView* edit = new Gui::EditorView(editor, Gui::getMainWindow()); + edit->open(fileName); + edit->resize(400, 300); + Gui::getMainWindow()->addWindow(edit); } } - - if (ext == QLatin1String("pov") || ext == QLatin1String("inc")) { - Gui::TextEditor* editor = new Gui::TextEditor(); - editor->setSyntaxHighlighter(new PovrayHighlighter(editor)); - Gui::EditorView* edit = new Gui::EditorView(editor, Gui::getMainWindow()); - edit->open(fileName); - edit->resize(400, 300); - Gui::getMainWindow()->addWindow(edit); + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); } - } PY_CATCH; + return Py::None(); + } - Py_Return; -} + Py::Object povViewCamera(const Py::Tuple& args) + { + // no arguments + if (!PyArg_ParseTuple(args.ptr(), "")) + throw Py::Exception(); + try { + std::string out; + const char* ppReturn=0; -/// return the camera definition of the active view -static PyObject * -povViewCamera(PyObject *self, PyObject *args) -{ - // no arguments - if (!PyArg_ParseTuple(args, "")) - return NULL; - PY_TRY { - std::string out; - const char* ppReturn=0; + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (doc) { + doc->sendMsgToFirstView(Gui::MDIView::getClassTypeId(), "GetCamera", &ppReturn); + } + else { + throw Py::RuntimeError("No active document found"); + } - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (doc) { - doc->sendMsgToFirstView(Gui::MDIView::getClassTypeId(), "GetCamera", &ppReturn); + if (!ppReturn) { + throw Py::RuntimeError("Could not read camera information from active view"); + } + + SoNode* rootNode; + SoInput in; + in.setBuffer((void*)ppReturn,std::strlen(ppReturn)); + SoDB::read(&in,rootNode); + + if (!rootNode || !rootNode->getTypeId().isDerivedFrom(SoCamera::getClassTypeId())) { + throw Py::RuntimeError("Could not read camera information from ASCII stream"); + } + + // root-node returned from SoDB::readAll() has initial zero + // ref-count, so reference it before we start using it to + // avoid premature destruction. + SoCamera * Cam = static_cast(rootNode); + Cam->ref(); + + SbRotation camrot = Cam->orientation.getValue(); + + SbVec3f upvec(0, 1, 0); // init to default up vector + camrot.multVec(upvec, upvec); + + SbVec3f lookat(0, 0, -1); // init to default view direction vector + camrot.multVec(lookat, lookat); + + SbVec3f pos = Cam->position.getValue(); + float Dist = Cam->focalDistance.getValue(); + Cam->unref(); // free memory + + // making gp out of the Coin stuff + gp_Vec gpPos(pos.getValue()[0],pos.getValue()[1],pos.getValue()[2]); + gp_Vec gpDir(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); + lookat *= Dist; + lookat += pos; + gp_Vec gpLookAt(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); + gp_Vec gpUp(upvec.getValue()[0],upvec.getValue()[1],upvec.getValue()[2]); + + // getting image format + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Raytracing"); + int width = hGrp->GetInt("OutputWidth", 800); + int height = hGrp->GetInt("OutputHeight", 600); + + // call the write method of PovTools.... + out = Raytracing::PovTools::getCamera(Raytracing::CamDef(gpPos,gpDir,gpLookAt,gpUp),width,height); + + return Py::String(out); } - else { - PyErr_SetString(PyExc_RuntimeError, "No active document found"); - return 0; + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); } + } - if (!ppReturn) { - PyErr_SetString(PyExc_RuntimeError, "Could not read camera information from active view"); - return 0; + Py::Object luxViewCamera(const Py::Tuple& args) + { + // no arguments + if (!PyArg_ParseTuple(args.ptr(), "")) + throw Py::Exception(); + try { + std::string out; + const char* ppReturn=0; + + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (doc) { + doc->sendMsgToFirstView(Gui::MDIView::getClassTypeId(), "GetCamera", &ppReturn); + } + else { + throw Py::RuntimeError("No active document found"); + } + + if (!ppReturn) { + throw Py::RuntimeError("Could not read camera information from active view"); + } + + SoNode* rootNode; + SoInput in; + in.setBuffer((void*)ppReturn,std::strlen(ppReturn)); + SoDB::read(&in,rootNode); + + if (!rootNode || !rootNode->getTypeId().isDerivedFrom(SoCamera::getClassTypeId())) { + throw Py::RuntimeError("Could not read camera information from ASCII stream"); + } + + // root-node returned from SoDB::readAll() has initial zero + // ref-count, so reference it before we start using it to + // avoid premature destruction. + SoCamera * Cam = static_cast(rootNode); + Cam->ref(); + + SbRotation camrot = Cam->orientation.getValue(); + + SbVec3f upvec(0, 1, 0); // init to default up vector + camrot.multVec(upvec, upvec); + + SbVec3f lookat(0, 0, -1); // init to default view direction vector + camrot.multVec(lookat, lookat); + + SbVec3f pos = Cam->position.getValue(); + float Dist = Cam->focalDistance.getValue(); + Cam->unref(); // free memory + + // making gp out of the Coin stuff + gp_Vec gpPos(pos.getValue()[0],pos.getValue()[1],pos.getValue()[2]); + gp_Vec gpDir(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); + lookat *= Dist; + lookat += pos; + gp_Vec gpLookAt(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); + gp_Vec gpUp(upvec.getValue()[0],upvec.getValue()[1],upvec.getValue()[2]); + + // call the write method of PovTools.... + out = Raytracing::LuxTools::getCamera(Raytracing::CamDef(gpPos,gpDir,gpLookAt,gpUp)); + + return Py::String(out); } - - SoNode* rootNode; - SoInput in; - in.setBuffer((void*)ppReturn,std::strlen(ppReturn)); - SoDB::read(&in,rootNode); - - if (!rootNode || !rootNode->getTypeId().isDerivedFrom(SoCamera::getClassTypeId())) { - PyErr_SetString(PyExc_RuntimeError, "Could not read camera information from ASCII stream"); - return 0; + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); } - - // root-node returned from SoDB::readAll() has initial zero - // ref-count, so reference it before we start using it to - // avoid premature destruction. - SoCamera * Cam = static_cast(rootNode); - Cam->ref(); - - SbRotation camrot = Cam->orientation.getValue(); - - SbVec3f upvec(0, 1, 0); // init to default up vector - camrot.multVec(upvec, upvec); - - SbVec3f lookat(0, 0, -1); // init to default view direction vector - camrot.multVec(lookat, lookat); - - SbVec3f pos = Cam->position.getValue(); - float Dist = Cam->focalDistance.getValue(); - Cam->unref(); // free memory - - // making gp out of the Coin stuff - gp_Vec gpPos(pos.getValue()[0],pos.getValue()[1],pos.getValue()[2]); - gp_Vec gpDir(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); - lookat *= Dist; - lookat += pos; - gp_Vec gpLookAt(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); - gp_Vec gpUp(upvec.getValue()[0],upvec.getValue()[1],upvec.getValue()[2]); - - // getting image format - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Raytracing"); - int width = hGrp->GetInt("OutputWidth", 800); - int height = hGrp->GetInt("OutputHeight", 600); - - // call the write method of PovTools.... - out = PovTools::getCamera(CamDef(gpPos,gpDir,gpLookAt,gpUp),width,height); - - return Py::new_reference_to(Py::String(out)); - } PY_CATCH; -} - -/// return a luxrender camera definition of the active view -static PyObject * -luxViewCamera(PyObject *self, PyObject *args) -{ - // no arguments - if (!PyArg_ParseTuple(args, "")) - return NULL; - PY_TRY { - std::string out; - const char* ppReturn=0; - - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (doc) { - doc->sendMsgToFirstView(Gui::MDIView::getClassTypeId(), "GetCamera", &ppReturn); - } - else { - PyErr_SetString(PyExc_RuntimeError, "No active document found"); - return 0; - } - - if (!ppReturn) { - PyErr_SetString(PyExc_RuntimeError, "Could not read camera information from active view"); - return 0; - } - - SoNode* rootNode; - SoInput in; - in.setBuffer((void*)ppReturn,std::strlen(ppReturn)); - SoDB::read(&in,rootNode); - - if (!rootNode || !rootNode->getTypeId().isDerivedFrom(SoCamera::getClassTypeId())) { - PyErr_SetString(PyExc_RuntimeError, "Could not read camera information from ASCII stream"); - return 0; - } - - // root-node returned from SoDB::readAll() has initial zero - // ref-count, so reference it before we start using it to - // avoid premature destruction. - SoCamera * Cam = static_cast(rootNode); - Cam->ref(); - - SbRotation camrot = Cam->orientation.getValue(); - - SbVec3f upvec(0, 1, 0); // init to default up vector - camrot.multVec(upvec, upvec); - - SbVec3f lookat(0, 0, -1); // init to default view direction vector - camrot.multVec(lookat, lookat); - - SbVec3f pos = Cam->position.getValue(); - float Dist = Cam->focalDistance.getValue(); - Cam->unref(); // free memory - - // making gp out of the Coin stuff - gp_Vec gpPos(pos.getValue()[0],pos.getValue()[1],pos.getValue()[2]); - gp_Vec gpDir(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); - lookat *= Dist; - lookat += pos; - gp_Vec gpLookAt(lookat.getValue()[0],lookat.getValue()[1],lookat.getValue()[2]); - gp_Vec gpUp(upvec.getValue()[0],upvec.getValue()[1],upvec.getValue()[2]); - - // call the write method of PovTools.... - out = LuxTools::getCamera(CamDef(gpPos,gpDir,gpLookAt,gpUp)); - - return Py::new_reference_to(Py::String(out)); - } PY_CATCH; -} - -/* registration table */ -struct PyMethodDef RaytracingGui_methods[] = { - {"open" ,open ,METH_VARARGS, - "open(string) -- Create a new text document and load the file into the document."}, - {"insert" ,open ,METH_VARARGS, - "insert(string,string) -- Create a new text document and load the file into the document."}, - {"povViewCamera" ,povViewCamera ,METH_VARARGS, - "string povViewCamera() -- returns the povray camera definition of the active 3D view."}, - {"luxViewCamera" ,luxViewCamera ,METH_VARARGS, - "string luxViewCamera() -- returns the luxrender camera definition of the active 3D view."}, - {NULL, NULL} + } }; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); +} + +} // namespace RaytracingGui diff --git a/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp b/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp index 2cad5fc3da..c0011a8b4f 100644 --- a/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp +++ b/src/Mod/ReverseEngineering/App/AppReverseEngineering.cpp @@ -524,8 +524,7 @@ Mesh.show(m) /* Python entry */ -extern "C" { -void ReenExport initReverseEngineering() +PyMODINIT_FUNC initReverseEngineering() { // load dependent module try { @@ -540,5 +539,3 @@ void ReenExport initReverseEngineering() new Reen::Module(); Base::Console().Log("Loading ReverseEngineering module... done\n"); } - -} // extern "C" diff --git a/src/Mod/ReverseEngineering/Gui/AppReverseEngineeringGui.cpp b/src/Mod/ReverseEngineering/Gui/AppReverseEngineeringGui.cpp index 4192223028..e91c2549fa 100644 --- a/src/Mod/ReverseEngineering/Gui/AppReverseEngineeringGui.cpp +++ b/src/Mod/ReverseEngineering/Gui/AppReverseEngineeringGui.cpp @@ -61,8 +61,7 @@ private: /* Python entry */ -extern "C" { -void ReenGuiExport initReverseEngineeringGui() +PyMODINIT_FUNC initReverseEngineeringGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -79,5 +78,3 @@ void ReenGuiExport initReverseEngineeringGui() // add resources and reloads the translators loadReverseEngineeringResource(); } - -} // extern "C" { diff --git a/src/Mod/Robot/App/AppRobot.cpp b/src/Mod/Robot/App/AppRobot.cpp index 0f961b0f07..999646875a 100644 --- a/src/Mod/Robot/App/AppRobot.cpp +++ b/src/Mod/Robot/App/AppRobot.cpp @@ -29,9 +29,12 @@ #include #include +#include +#include #include "Robot6AxisPy.h" #include "Robot6Axis.h" +#include "Simulation.h" #include "TrajectoryPy.h" #include "Trajectory.h" #include "PropertyTrajectory.h" @@ -43,15 +46,50 @@ #include "TrajectoryCompound.h" #include "TrajectoryDressUpObject.h" -extern struct PyMethodDef Robot_methods[]; +namespace Robot { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("Robot") + { + add_varargs_method("simulateToFile",&Module::simulateToFile, + "simulateToFile(Robot,Trajectory,TickSize,FileName) - runs the simulation and write the result to a file." + ); + initialize("This module is the Robot module."); // register with Python + } -PyDoc_STRVAR(module_Robot_doc, -"This module is the Robot module."); + virtual ~Module() {} + +private: + Py::Object simulateToFile(const Py::Tuple& args) + { + PyObject *pcRobObj; + PyObject *pcTracObj; + float tick; + char* FileName; + + if (!PyArg_ParseTuple(args.ptr(), "O!O!fs", &(Robot6AxisPy::Type), &pcRobObj, + &(TrajectoryPy::Type), &pcTracObj, + &tick,&FileName)) + throw Py::Exception(); + + try { + Robot::Trajectory &Trac = * static_cast(pcTracObj)->getTrajectoryPtr(); + Robot::Robot6Axis &Rob = * static_cast(pcRobObj)->getRobot6AxisPtr(); + Simulation Sim(Trac,Rob); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + + return Py::Float(0.0); + } +}; +} // namespace Robot /* Python entry */ -extern "C" { -void RobotExport initRobot() +PyMODINIT_FUNC initRobot() { // load dependent module try { @@ -62,10 +100,9 @@ void RobotExport initRobot() return; } - PyObject* robotModule = Py_InitModule3("Robot", Robot_methods, module_Robot_doc); /* mod name, table ptr */ + PyObject* robotModule = (new Robot::Module())->module().ptr(); Base::Console().Log("Loading Robot module... done\n"); - // Add Types to module Base::Interpreter().addType(&Robot::Robot6AxisPy ::Type,robotModule,"Robot6Axis"); Base::Interpreter().addType(&Robot::WaypointPy ::Type,robotModule,"Waypoint"); @@ -75,7 +112,7 @@ void RobotExport initRobot() // NOTE: To finish the initialization of our own type objects we must // call PyType_Ready, otherwise we run into a segmentation fault, later on. // This function is responsible for adding inherited slots from a type's base class. - + Robot::Robot6Axis ::init(); Robot::RobotObject ::init(); Robot::TrajectoryObject ::init(); @@ -86,5 +123,3 @@ void RobotExport initRobot() Robot::TrajectoryCompound ::init(); Robot::TrajectoryDressUpObject ::init(); } - -} // extern "C" diff --git a/src/Mod/Robot/App/AppRobotPy.cpp b/src/Mod/Robot/App/AppRobotPy.cpp deleted file mode 100644 index 6bd8513e4e..0000000000 --- a/src/Mod/Robot/App/AppRobotPy.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -#endif - -#include -#include - -#include "TrajectoryPy.h" -#include "Robot6AxisPy.h" -#include "Simulation.h" - -#include "RobotAlgos.h" - -using namespace Robot; - -static PyObject * -simulateToFile(PyObject *self, PyObject *args) -{ - PyObject *pcRobObj; - PyObject *pcTracObj; - float tick; - char* FileName; - - if (!PyArg_ParseTuple(args, "O!O!fs", &(Robot6AxisPy::Type), &pcRobObj, - &(TrajectoryPy::Type), &pcTracObj, - &tick,&FileName - ) ) - return NULL; // NULL triggers exception - - PY_TRY { - Robot::Trajectory &Trac = * static_cast(pcTracObj)->getTrajectoryPtr(); - Robot::Robot6Axis &Rob = * static_cast(pcRobObj)->getRobot6AxisPtr(); - Simulation Sim(Trac,Rob); - - - - } PY_CATCH; - - return Py::new_reference_to(Py::Float(0.0)); - -} - - -/* registration table */ -struct PyMethodDef Robot_methods[] = { - {"simulateToFile" ,simulateToFile ,METH_VARARGS, - "void simulateToFile(Robot,Trajectory,TickSize,FileName) - runs the simulation and write the result to a file."}, - {NULL, NULL} /* end of table marker */ -}; diff --git a/src/Mod/Robot/App/CMakeLists.txt b/src/Mod/Robot/App/CMakeLists.txt index 8374829847..ceea3063bc 100644 --- a/src/Mod/Robot/App/CMakeLists.txt +++ b/src/Mod/Robot/App/CMakeLists.txt @@ -45,7 +45,6 @@ SET(Python_SRCS SET(Mod_SRCS AppRobot.cpp - AppRobotPy.cpp PreCompiled.cpp PreCompiled.h ) diff --git a/src/Mod/Robot/Gui/AppRobotGui.cpp b/src/Mod/Robot/Gui/AppRobotGui.cpp index 0b9c20c408..9e5e9066cd 100644 --- a/src/Mod/Robot/Gui/AppRobotGui.cpp +++ b/src/Mod/Robot/Gui/AppRobotGui.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -50,15 +53,26 @@ void loadRobotResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef RobotGui_Import_methods[]; +namespace RobotGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("RobotGui") + { + initialize("This module is the RobotGui module."); // register with Python + } + + virtual ~Module() {} + +private: +}; +} // namespace RobotGui /* Python entry */ -extern "C" { -void RobotGuiExport initRobotGui() +PyMODINIT_FUNC initRobotGui() { - if (!Gui::Application::Instance) { + if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); return; } @@ -82,7 +96,7 @@ void RobotGuiExport initRobotGui() PyErr_SetString(PyExc_ImportError, e.what()); return; } - (void) Py_InitModule("RobotGui", RobotGui_Import_methods); /* mod name, table ptr */ + (void)new RobotGui::Module(); Base::Console().Log("Loading GUI of Robot module... done\n"); // instantiating the commands @@ -93,14 +107,12 @@ void RobotGuiExport initRobotGui() // addition objects RobotGui::Workbench ::init(); - RobotGui::ViewProviderRobotObject ::init(); - RobotGui::ViewProviderTrajectory ::init(); - RobotGui::ViewProviderEdge2TracObject ::init(); - RobotGui::ViewProviderTrajectoryCompound ::init(); - RobotGui::ViewProviderTrajectoryDressUp ::init(); + RobotGui::ViewProviderRobotObject ::init(); + RobotGui::ViewProviderTrajectory ::init(); + RobotGui::ViewProviderEdge2TracObject ::init(); + RobotGui::ViewProviderTrajectoryCompound ::init(); + RobotGui::ViewProviderTrajectoryDressUp ::init(); // add resources and reloads the translators loadRobotResource(); } - -} // extern "C" { diff --git a/src/Mod/Robot/Gui/AppRobotGuiPy.cpp b/src/Mod/Robot/Gui/AppRobotGuiPy.cpp deleted file mode 100644 index c006ecd41f..0000000000 --- a/src/Mod/Robot/Gui/AppRobotGuiPy.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2008 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -#endif - - -/* registration table */ -struct PyMethodDef RobotGui_Import_methods[] = { - {NULL, NULL} /* end of table marker */ -}; diff --git a/src/Mod/Robot/Gui/CMakeLists.txt b/src/Mod/Robot/Gui/CMakeLists.txt index 6c17aa8931..611c0d5464 100644 --- a/src/Mod/Robot/Gui/CMakeLists.txt +++ b/src/Mod/Robot/Gui/CMakeLists.txt @@ -62,7 +62,6 @@ SOURCE_GROUP("Qt" FILES ${PartDesignGui_MOC_SRCS}) SET(RobotGui_SRCS_Module AppRobotGui.cpp - AppRobotGuiPy.cpp Resources/Robot.qrc PreCompiled.cpp PreCompiled.h @@ -94,7 +93,7 @@ SET(RobotGui_SRCS_ViewProvider SOURCE_GROUP("ViewProvider" FILES ${RobotGui_SRCS_ViewProvider}) SET(RobotGui_SRCS_TaskBoxes - TaskRobot6Axis.ui + TaskRobot6Axis.ui TaskRobot6Axis.cpp TaskRobot6Axis.h TaskTrajectory.ui @@ -125,21 +124,21 @@ SET(RobotGui_SRCS_TaskDlg TaskDlgSimulate.cpp TaskDlgEdge2Trac.h TaskDlgEdge2Trac.cpp - TaskDlgTrajectoryCompound.h - TaskDlgTrajectoryCompound.cpp - TaskDlgTrajectoryDressUp.h - TaskDlgTrajectoryDressUp.cpp + TaskDlgTrajectoryCompound.h + TaskDlgTrajectoryCompound.cpp + TaskDlgTrajectoryDressUp.h + TaskDlgTrajectoryDressUp.cpp ) SOURCE_GROUP("Task_Dialogs" FILES ${RobotGui_SRCS_TaskDlg}) SET(RobotGui_SRCS ${RobotGui_UIC_HDRS} ${RobotResource_SRCS} - ${RobotGui_SRCS_Module} - ${RobotGui_SRCS_ViewProvider} - ${RobotGui_SRCS_Commands} - ${RobotGui_SRCS_TaskBoxes} - ${RobotGui_SRCS_TaskDlg} + ${RobotGui_SRCS_Module} + ${RobotGui_SRCS_ViewProvider} + ${RobotGui_SRCS_Commands} + ${RobotGui_SRCS_TaskBoxes} + ${RobotGui_SRCS_TaskDlg} ) diff --git a/src/Mod/Sandbox/App/AppSandbox.cpp b/src/Mod/Sandbox/App/AppSandbox.cpp index 802aa3904e..051d7bd69e 100644 --- a/src/Mod/Sandbox/App/AppSandbox.cpp +++ b/src/Mod/Sandbox/App/AppSandbox.cpp @@ -146,24 +146,22 @@ public: Py::String m_value; }; -} // namespace Sandbox - /* module functions */ -class SandboxModule : public Py::ExtensionModule +class Module : public Py::ExtensionModule { public: - SandboxModule() : Py::ExtensionModule("Sandbox") + Module() : Py::ExtensionModule("Sandbox") { Sandbox::PythonBaseClass::init_type(); Sandbox::DocumentProtectorPy::init_type(); add_varargs_method("DocumentProtector", - &SandboxModule::new_DocumentProtector, + &Module::new_DocumentProtector, "DocumentProtector(Document)"); Sandbox::DocumentObjectProtectorPy::init_type(); add_varargs_method("DocumentObjectProtector", - &SandboxModule::new_DocumentObjectProtector, + &Module::new_DocumentObjectProtector, "DocumentObjectProtector(DocumentObject)"); initialize("This module is the Sandbox module"); // register with Python @@ -172,7 +170,7 @@ public: d["PythonBaseClass"] = x; } - virtual ~SandboxModule() {} + virtual ~Module() {} private: Py::Object new_DocumentProtector(const Py::Tuple& args) @@ -193,18 +191,17 @@ private: } }; +} // namespace Sandbox + /* Python entry */ -extern "C" { -void SandboxAppExport initSandbox() { +PyMODINIT_FUNC initSandbox() { Sandbox::DocumentProtector ::init(); Sandbox::SandboxObject ::init(); // the following constructor call registers our extension module // with the Python runtime system - (void)new SandboxModule; + (void)new Sandbox::Module; Base::Console().Log("Loading Sandbox module... done\n"); } - -} // extern "C" diff --git a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp index bb0bfd12cc..5e098d4b54 100644 --- a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp +++ b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp @@ -187,20 +187,21 @@ private: double radius; }; -class SandboxModuleGui : public Py::ExtensionModule +namespace SandboxGui { +class Module : public Py::ExtensionModule { public: - SandboxModuleGui() : Py::ExtensionModule("SandboxGui") + Module() : Py::ExtensionModule("SandboxGui") { - add_varargs_method("interactiveFilletArc",&SandboxModuleGui::interactiveFilletArc, + add_varargs_method("interactiveFilletArc",&Module::interactiveFilletArc, "Interactive fillet arc"); - add_varargs_method("xmlReader",&SandboxModuleGui::xmlReader, + add_varargs_method("xmlReader",&Module::xmlReader, "Read XML"); initialize("This module is the SandboxGui module"); // register with Python } - virtual ~SandboxModuleGui() {} + virtual ~Module() {} private: Py::Object interactiveFilletArc(const Py::Tuple& args) @@ -238,10 +239,10 @@ private: } }; +} // namespace SandboxGui /* Python entry */ -extern "C" { -void SandboxGuiExport initSandboxGui() +PyMODINIT_FUNC initSandboxGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -264,8 +265,6 @@ void SandboxGuiExport initSandboxGui() // the following constructor call registers our extension module // with the Python runtime system - (void)new SandboxModuleGui; + (void)new SandboxGui::Module; Base::Console().Log("Loading GUI of Sandbox module... done\n"); } - -} // extern "C" diff --git a/src/Mod/Sketcher/App/AppSketcher.cpp b/src/Mod/Sketcher/App/AppSketcher.cpp index 487a7473b6..29b28c7938 100644 --- a/src/Mod/Sketcher/App/AppSketcher.cpp +++ b/src/Mod/Sketcher/App/AppSketcher.cpp @@ -28,7 +28,7 @@ #include #include - + #include "SketchObjectSF.h" #include "SketchObject.h" #include "Constraint.h" @@ -38,15 +38,12 @@ #include "PropertyConstraintList.h" -extern struct PyMethodDef Sketcher_methods[]; - -PyDoc_STRVAR(module_Sketcher_doc, -"This module is the Sketcher module."); - +namespace Sketcher { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void SketcherExport initSketcher() +PyMODINIT_FUNC initSketcher() { // load dependent module try { @@ -56,8 +53,9 @@ void SketcherExport initSketcher() PyErr_SetString(PyExc_ImportError, e.what()); return; } - PyObject* sketcherModule = Py_InitModule3("Sketcher", Sketcher_methods, module_Sketcher_doc); /* mod name, table ptr */ - + + PyObject* sketcherModule = Sketcher::initModule(); + // Add Types to module Base::Interpreter().addType(&Sketcher::ConstraintPy ::Type,sketcherModule,"Constraint"); Base::Interpreter().addType(&Sketcher::SketchPy ::Type,sketcherModule,"Sketch"); @@ -75,15 +73,4 @@ void SketcherExport initSketcher() Sketcher::PropertyConstraintList::init(); Base::Console().Log("Loading Sketcher module... done\n"); - -} - - - -} // extern "C" - -// debug print for sketchsolv -void debugprint(std::string s) -{ - Base::Console().Log(s.c_str()); } diff --git a/src/Mod/Sketcher/App/AppSketcherPy.cpp b/src/Mod/Sketcher/App/AppSketcherPy.cpp index d75f9d85ac..b26e57294a 100644 --- a/src/Mod/Sketcher/App/AppSketcherPy.cpp +++ b/src/Mod/Sketcher/App/AppSketcherPy.cpp @@ -36,103 +36,95 @@ #include #include +#include +#include + // Things from the part module #include #include #include "SketchObjectSF.h" -using Base::Console; -using namespace Part; -using namespace std; - -/* module functions */ -static PyObject * open(PyObject *self, PyObject *args) +namespace Sketcher { +class Module : public Py::ExtensionModule { - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("Sketcher") + { + add_varargs_method("open",&Module::open + ); + add_varargs_method("insert",&Module::insert + ); + initialize("This module is the Sketcher module."); // register with Python + } + + virtual ~Module() {} + +private: + 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); - PY_TRY { - } PY_CATCH; //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"); + // extract extension + if (file.extension().empty()) + throw Py::RuntimeError("No file extension"); - //if (file.hasExtension("igs") || file.hasExtension("iges")) { - // // create new document and add Import feature - // App::Document *pcDoc = App::GetApplication().newDocument(file.fileNamePure().c_str()); - // Part::ImportIges *pcFeature = (Part::ImportIges*) pcDoc->addObject("Part::ImportIges",file.fileNamePure().c_str()); - // pcFeature->FileName.setValue(Name); - // pcDoc->recompute(); - //} - // else { - Py_Error(Base::BaseExceptionFreeCADError,"unknown file ending"); - //} + throw Py::RuntimeError("Unknown file extension"); + return Py::None(); + } - Py_Return; -} + 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); -/* 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); + try { + //Base::Console().Log("Insert in Part with %s",Name); + Base::FileInfo file(EncodedName.c_str()); - PY_TRY { - //Base::Console().Log("Insert in Part with %s",Name); - Base::FileInfo file(EncodedName.c_str()); + // extract extension + if (file.extension().empty()) + throw Py::RuntimeError("No file extension"); - // 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); + App::Document *pcDoc = App::GetApplication().getDocument(DocName); + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument(DocName); + } + + if (file.hasExtension("skf")) { + Sketcher::SketchObjectSF *pcFeature = (Sketcher::SketchObjectSF *)pcDoc->addObject("Sketcher::SketchObjectSF",file.fileNamePure().c_str()); + pcFeature->SketchFlatFile.setValue(EncodedName.c_str()); + + pcDoc->recompute(); + } + else { + throw Py::RuntimeError("Unknown file extension"); + } } - - if (file.hasExtension("skf")) { - - Sketcher::SketchObjectSF *pcFeature = (Sketcher::SketchObjectSF *)pcDoc->addObject("Sketcher::SketchObjectSF",file.fileNamePure().c_str()); - pcFeature->SketchFlatFile.setValue(EncodedName.c_str()); - - pcDoc->recompute(); + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); } - else { - Py_Error(Base::BaseExceptionFreeCADError,"unknown file ending"); - } - - } PY_CATCH; - - Py_Return; -} - -/* module functions */ -//static PyObject * read(PyObject *self, PyObject *args) -//{ -// const char* Name; -// if (!PyArg_ParseTuple(args, "s",&Name)) -// return NULL; -// PY_TRY { -// } PY_CATCH; -// -// Py_Return; -//} - -/* registration table */ -struct PyMethodDef Sketcher_methods[] = { - {"open" , open, 1}, - {"insert" , insert, 1}, -// {"read" , read, 1}, - {NULL, NULL} /* end of table marker */ + return Py::None(); + } }; + +/// @cond DOXERR +PyObject* initModule() +{ + return (new Module())->module().ptr(); +} +/// @endcond + +} // namespace Sketcher diff --git a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp index 1c51a371ab..1d9bace667 100644 --- a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp +++ b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include #include @@ -54,13 +57,24 @@ void loadSketcherResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef SketcherGui_Import_methods[]; +namespace SketcherGui { +class Module : public Py::ExtensionModule +{ +public: + Module() : Py::ExtensionModule("SketcherGui") + { + initialize("This module is the SketcherGui module."); // register with Python + } + + virtual ~Module() {} + +private: +}; +} // namespace SketcherGui /* Python entry */ -extern "C" { -void SketcherGuiExport initSketcherGui() +PyMODINIT_FUNC initSketcherGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); @@ -75,7 +89,7 @@ void SketcherGuiExport initSketcherGui() return; } - (void) Py_InitModule("SketcherGui", SketcherGui_Import_methods); /* mod name, table ptr */ + (void)new SketcherGui::Module(); Base::Console().Log("Loading GUI of Sketcher module... done\n"); // instantiating the commands @@ -101,5 +115,3 @@ void SketcherGuiExport initSketcherGui() // add resources and reloads the translators loadSketcherResource(); } - -} // extern "C" { diff --git a/src/Mod/Sketcher/Gui/AppSketcherGuiPy.cpp b/src/Mod/Sketcher/Gui/AppSketcherGuiPy.cpp deleted file mode 100644 index 703b3a2fa4..0000000000 --- a/src/Mod/Sketcher/Gui/AppSketcherGuiPy.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2008 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -#endif - - -#include -#include -#include -#include -#include -#include - - - -/* 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 { - } PY_CATCH; - - Py_Return; -} - - -/* module functions */ -static PyObject * -insert(PyObject *self, PyObject *args) -{ - // not supported to insert an image (by dropping on an image view) - // hence do nothing - Py_Return; -} - -/* registration table */ -struct PyMethodDef SketcherGui_Import_methods[] = { - {"open" ,open , 1}, /* method name, C func ptr, always-tuple */ - {"insert" ,insert, 1}, - {NULL, NULL} /* end of table marker */ -}; diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt index 3a88305c0e..a3e29e0ff4 100644 --- a/src/Mod/Sketcher/Gui/CMakeLists.txt +++ b/src/Mod/Sketcher/Gui/CMakeLists.txt @@ -65,7 +65,6 @@ SET(SketcherGui_SRCS ${SketcherGui_SRCS} ${SketcherGui_UIC_HDRS} AppSketcherGui.cpp - AppSketcherGuiPy.cpp GeometryCreationMode.h Command.cpp CommandCreateGeo.cpp diff --git a/src/Mod/Test/Gui/AppTestGui.cpp b/src/Mod/Test/Gui/AppTestGui.cpp index 548e431064..f9ac6d764e 100644 --- a/src/Mod/Test/Gui/AppTestGui.cpp +++ b/src/Mod/Test/Gui/AppTestGui.cpp @@ -88,8 +88,7 @@ void loadTestResource() } /* Python entry */ -extern "C" { -void AppTestGuiExport initQtUnitGui() +PyMODINIT_FUNC initQtUnitGui() { // the following constructor call registers our extension module // with the Python runtime system @@ -101,5 +100,3 @@ void AppTestGuiExport initQtUnitGui() loadTestResource(); return; } - -} // extern "C" diff --git a/src/Mod/Web/Gui/AppWebGui.cpp b/src/Mod/Web/Gui/AppWebGui.cpp index e70ae84d92..df8c9420cf 100644 --- a/src/Mod/Web/Gui/AppWebGui.cpp +++ b/src/Mod/Web/Gui/AppWebGui.cpp @@ -60,7 +60,7 @@ public: ); add_varargs_method("openBrowserHTML",&Module::openBrowserHTML ); - initialize("This module is the Web module."); // register with Python + initialize("This module is the WebGui module."); // register with Python } virtual ~Module() {} diff --git a/src/Tools/MakeMacBundleRelocatable.py b/src/Tools/MakeMacBundleRelocatable.py index d44a94963d..3825034c0d 100644 --- a/src/Tools/MakeMacBundleRelocatable.py +++ b/src/Tools/MakeMacBundleRelocatable.py @@ -1,9 +1,10 @@ import os import sys -import subprocess +from subprocess import Popen, PIPE, check_call, check_output import pprint +import re -SYS_PATHS = ["/System/", "/usr/lib/"] +SYS_PATHS = ["/System/", "/usr/lib/", "/Library/Frameworks/"] class LibraryNotFound(Exception): pass @@ -63,8 +64,9 @@ class DepsGraph: stack.append(ck) operation(self, self.graph[node_key], *op_args) + def is_macho(path): - output = subprocess.check_output(["file", path]) + output = check_output(["file", path]) if output.count("Mach-O") != 0: return True @@ -83,7 +85,7 @@ def get_path(name, search_paths): return None def list_install_names(path_macho): - output = subprocess.check_output(["otool", "-L", path_macho]) + output = check_output(["otool", "-L", path_macho]) lines = output.split("\t") libs = [] @@ -129,7 +131,7 @@ def create_dep_nodes(install_names, search_paths): path = get_path(lib_name, search_paths) if install_path != "" and lib[0] != "@": - #we have an absolte path install name + #we have an absolute path install name if not path: path = install_path @@ -148,7 +150,6 @@ def paths_at_depth(prefix, paths, depth): filtered.append(p) return filtered - def should_visit(prefix, path_filters, path): s_path = path.strip('/').split('/') filters = [] @@ -227,14 +228,44 @@ def in_bundle(lib, bundle_path): def copy_into_bundle(graph, node, bundle_path): if not in_bundle(node.path, bundle_path): - subprocess.check_call(["cp", "-L", os.path.join(node.path, node.name), - os.path.join(bundle_path, "lib", node.name)]) + check_call([ "cp", "-L", os.path.join(node.path, node.name), + os.path.join(bundle_path, "lib", node.name) ]) + node.path = os.path.join(bundle_path, "lib") #fix permissions - subprocess.check_call(["chmod", "a+w", os.path.join(bundle_path, - "lib", node.name)]) - + check_call([ "chmod", "a+w", + os.path.join(bundle_path, "lib", node.name) ]) + +def get_rpaths(library): + "Returns a list of rpaths specified within library" + + out = check_output(["otool", "-l", library]) + + pathRegex = r"^path (.*) \(offset \d+\)$" + expectingRpath = False + rpaths = [] + for line in out.split('\n'): + line = line.strip() + + if "cmd LC_RPATH" in line: + expectingRpath = True + continue + + if "Load command" in line: + expectingRpath = False + continue + + if not expectingRpath: + continue + + m = re.match(pathRegex, line) + if m: + rpaths.append(m.group(1)) + expectingRpath = False + + return rpaths + def add_rpaths(graph, node, bundle_path): if node.children: lib = os.path.join(node.path, node.name) @@ -245,8 +276,8 @@ def add_rpaths(graph, node, bundle_path): for install_name in install_names: name = os.path.basename(install_name) #change install names to use rpaths - subprocess.check_call(["install_name_tool", "-change", - install_name, "@rpath/" + name, lib]) + check_call([ "install_name_tool", "-change", + install_name, "@rpath/" + name, lib ]) dep_node = node.children[node.children.index(name)] rel_path = os.path.relpath(graph.get_node(dep_node).path, @@ -258,8 +289,12 @@ def add_rpaths(graph, node, bundle_path): rpath = "@loader_path/" + rel_path + "/" if rpath not in rpaths: rpaths.append(rpath) - for path in rpaths: - subprocess.call(["install_name_tool", "-add_rpath", path, lib]) + + for rpath in rpaths: + # Ensure that lib has rpath set + if not rpath in get_rpaths(lib): + check_output([ "install_name_tool", + "-add_rpath", rpath, lib ]) def main(): if len(sys.argv) < 2: