diff --git a/src/Mod/Path/App/AppPath.cpp b/src/Mod/Path/App/AppPath.cpp index 1e7a055943..dce12ea957 100644 --- a/src/Mod/Path/App/AppPath.cpp +++ b/src/Mod/Path/App/AppPath.cpp @@ -30,14 +30,8 @@ #include "CommandPy.h" #include "Path.h" #include "PathPy.h" -#include "Tool.h" -#include "Tooltable.h" -#include "ToolPy.h" -#include "TooltablePy.h" #include "PropertyPath.h" #include "FeaturePath.h" -#include "PropertyTool.h" -#include "PropertyTooltable.h" #include "FeaturePathCompound.h" #include "FeaturePathShape.h" #include "AreaPy.h" @@ -52,12 +46,12 @@ #include "VoronoiVertexPy.h" -namespace Path { +namespace PathApp { extern PyObject* initModule(); } /* Python entry */ -PyMOD_INIT_FUNC(Path) +PyMOD_INIT_FUNC(PathApp) { // load dependent module try { @@ -68,7 +62,7 @@ PyMOD_INIT_FUNC(Path) PyMOD_Return(nullptr); } - PyObject* pathModule = Path::initModule(); + PyObject* pathModule = PathApp::initModule(); Base::Console().Log("Loading Path module... done\n"); Py::Object module(pathModule); @@ -76,8 +70,6 @@ PyMOD_INIT_FUNC(Path) // 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::AreaPy ::Type, pathModule, "Area"); PyObject* voronoiModule(module.getAttr("Voronoi").ptr()); @@ -91,13 +83,9 @@ PyMOD_INIT_FUNC(Path) // This function is responsible for adding inherited slots from a type's base class. Path::Command ::init(); Path::Toolpath ::init(); - Path::Tool ::init(); - Path::Tooltable ::init(); Path::PropertyPath ::init(); Path::Feature ::init(); Path::FeaturePython ::init(); - Path::PropertyTool ::init(); - Path::PropertyTooltable ::init(); Path::FeatureCompound ::init(); Path::FeatureCompoundPython ::init(); Path::FeatureShape ::init(); diff --git a/src/Mod/Path/App/AppPathPy.cpp b/src/Mod/Path/App/AppPathPy.cpp index ac33305e21..e3305aff80 100644 --- a/src/Mod/Path/App/AppPathPy.cpp +++ b/src/Mod/Path/App/AppPathPy.cpp @@ -90,7 +90,7 @@ PyErr_SetString(Base::PyExc_FC_GeneralError,e); \ } throw Py::Exception(); -namespace Path { +namespace PathApp { class VoronoiModule : public Py::ExtensionModule { public: @@ -106,7 +106,7 @@ namespace Path { VoronoiModule voronoi; public: - Module() : Py::ExtensionModule("Path") + Module() : Py::ExtensionModule("PathApp") { add_varargs_method("write",&Module::write, "write(object,filename): Exports a given path object to a GCode file" @@ -162,7 +162,7 @@ namespace Path { 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(); + const Path::Toolpath& path = static_cast(obj)->Path.getValue(); std::string gcode = path.toGCode(); Base::ofstream ofile(file); ofile << gcode; @@ -204,7 +204,7 @@ namespace Path { std::stringstream buffer; buffer << filestr.rdbuf(); std::string gcode = buffer.str(); - Toolpath path; + Path::Toolpath path; path.setFromGCode(gcode); Path::Feature *object = static_cast(pcDoc->addObject("Path::Feature",file.fileNamePure().c_str())); object->Path.setValue(path); @@ -222,14 +222,14 @@ namespace Path { { PyObject *pcObj; char *name = "Path"; - if (!PyArg_ParseTuple(args.ptr(), "O!|s", &(PathPy::Type), &pcObj, &name)) + if (!PyArg_ParseTuple(args.ptr(), "O!|s", &(Path::PathPy::Type), &pcObj, &name)) throw Py::Exception(); try { App::Document *pcDoc = App::GetApplication().getActiveDocument(); if (!pcDoc) pcDoc = App::GetApplication().newDocument(); - PathPy* pPath = static_cast(pcObj); + Path::PathPy* pPath = static_cast(pcObj); Path::Feature *pcFeature = static_cast(pcDoc->addObject("Path::Feature", name)); Path::Toolpath* pa = pPath->getToolpathPtr(); if (!pa) { @@ -313,7 +313,7 @@ namespace Path { } ExpEdges.Next(); } - return Py::asObject(new PathPy(new Path::Toolpath(result))); + return Py::asObject(new Path::PathPy(new Path::Toolpath(result))); } else { throw Py::TypeError("the given shape must be a wire"); } @@ -365,13 +365,13 @@ namespace Path { try { gp_Pnt pend; - std::unique_ptr path(new Toolpath); - Area::toPath(*path,shapes,start?&pstart:nullptr, &pend, + std::unique_ptr path(new Path::Toolpath); + Path::Area::toPath(*path,shapes,start?&pstart:nullptr, &pend, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_PATH)); if (!Base::asBoolean(return_end)) - return Py::asObject(new PathPy(path.release())); + return Py::asObject(new Path::PathPy(path.release())); Py::Tuple tuple(2); - tuple.setItem(0, Py::asObject(new PathPy(path.release()))); + tuple.setItem(0, Py::asObject(new Path::PathPy(path.release()))); tuple.setItem(1, Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(),pend.Y(),pend.Z())))); return tuple; } PATH_CATCH @@ -419,8 +419,8 @@ namespace Path { } try { - bool need_arc_plane = arc_plane==Area::ArcPlaneAuto; - std::list wires = Area::sortWires(shapes, start != nullptr, &pstart, + bool need_arc_plane = arc_plane == Path::Area::ArcPlaneAuto; + std::list wires = Path::Area::sortWires(shapes, start != nullptr, &pstart, &pend, nullptr, &arc_plane, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT)); Py::List list; for(auto &wire : wires) { diff --git a/src/Mod/Path/App/CMakeLists.txt b/src/Mod/Path/App/CMakeLists.txt index fa9a52c302..9fb6fc9bb1 100644 --- a/src/Mod/Path/App/CMakeLists.txt +++ b/src/Mod/Path/App/CMakeLists.txt @@ -31,8 +31,6 @@ set(Path_LIBS generate_from_xml(CommandPy) generate_from_xml(PathPy) -generate_from_xml(ToolPy) -generate_from_xml(TooltablePy) generate_from_xml(FeaturePathCompoundPy) generate_from_xml(AreaPy) generate_from_xml(FeatureAreaPy) @@ -46,10 +44,6 @@ SET(Python_SRCS CommandPyImp.cpp PathPy.xml PathPyImp.cpp - ToolPy.xml - ToolPyImp.cpp - TooltablePy.xml - TooltablePyImp.cpp FeaturePathCompoundPy.xml FeaturePathCompoundPyImp.cpp AreaPy.xml @@ -78,18 +72,10 @@ SET(Path_SRCS Command.h Path.cpp Path.h - Tool.cpp - Tool.h - Tooltable.cpp - Tooltable.h PropertyPath.cpp PropertyPath.h FeaturePath.cpp FeaturePath.h - PropertyTool.cpp - PropertyTool.h - PropertyTooltable.cpp - PropertyTooltable.h FeaturePathCompound.cpp FeaturePathCompound.h FeaturePathShape.cpp @@ -163,7 +149,7 @@ if(FREECAD_USE_PCH) endif(FREECAD_USE_PCH) -SET_BIN_DIR(Path Path /Mod/Path) +SET_BIN_DIR(Path PathApp /Mod/Path) SET_PYTHON_PREFIX_SUFFIX(Path) INSTALL(TARGETS Path DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/Mod/Path/App/PropertyTool.cpp b/src/Mod/Path/App/PropertyTool.cpp deleted file mode 100644 index 43741c1d01..0000000000 --- a/src/Mod/Path/App/PropertyTool.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 - -#include "PropertyTool.h" -#include "ToolPy.h" - -using namespace Path; - -TYPESYSTEM_SOURCE(Path::PropertyTool, App::Property) - -PropertyTool::PropertyTool() -{ -} - -PropertyTool::~PropertyTool() -{ -} - -void PropertyTool::setValue(const Tool& tt) -{ - aboutToSetValue(); - _Tool = tt; - hasSetValue(); -} - - -const Tool &PropertyTool::getValue()const -{ - return _Tool; -} - -PyObject *PropertyTool::getPyObject() -{ - return new ToolPy(new Tool(_Tool)); -} - -void PropertyTool::setPyObject(PyObject *value) -{ - if (PyObject_TypeCheck(value, &(ToolPy::Type))) { - ToolPy *pcObject = static_cast(value); - setValue(*pcObject->getToolPtr()); - } - else { - std::string error = std::string("type must be 'Tool', not "); - error += value->ob_type->tp_name; - throw Base::TypeError(error); - } -} - -App::Property *PropertyTool::Copy() const -{ - PropertyTool *prop = new PropertyTool(); - prop->_Tool = this->_Tool; - - return prop; -} - -void PropertyTool::Paste(const App::Property &from) -{ - aboutToSetValue(); - _Tool = dynamic_cast(from)._Tool; - hasSetValue(); -} - -unsigned int PropertyTool::getMemSize () const -{ - return _Tool.getMemSize(); -} - -void PropertyTool::Save (Base::Writer &writer) const -{ - _Tool.Save(writer); -} - -void PropertyTool::Restore(Base::XMLReader &reader) -{ - Path::Tool temp; - temp.Restore(reader); - setValue(temp); -} - - diff --git a/src/Mod/Path/App/PropertyTool.h b/src/Mod/Path/App/PropertyTool.h deleted file mode 100644 index d4fc146d65..0000000000 --- a/src/Mod/Path/App/PropertyTool.h +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 PROPERTYTOOL_H -#define PROPERTYTOOL_H - -#include "Tool.h" -#include - -namespace Path -{ - - -/** The tool property class. */ -class PathExport PropertyTool : public App::Property -{ - TYPESYSTEM_HEADER(); - -public: - PropertyTool(); - ~PropertyTool(); - - /** @name Getter/setter */ - //@{ - /// set the part shape - void setValue(const Tool&); - /// get the part shape - const Tool &getValue(void) const; - //@} - - /** @name Python interface */ - //@{ - PyObject* getPyObject(void); - void setPyObject(PyObject *value); - //@} - - /** @name Save/restore */ - //@{ - void Save (Base::Writer &writer) const; - void Restore(Base::XMLReader &reader); - - App::Property *Copy(void) const; - void Paste(const App::Property &from); - unsigned int getMemSize (void) const; - //@} - -private: - Tool _Tool; -}; - - -} //namespace Path - - -#endif // PROPERTYTOOL_H diff --git a/src/Mod/Path/App/PropertyTooltable.cpp b/src/Mod/Path/App/PropertyTooltable.cpp deleted file mode 100644 index 7c4a3bc8f5..0000000000 --- a/src/Mod/Path/App/PropertyTooltable.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 - -#include "PropertyTooltable.h" -#include "TooltablePy.h" - -using namespace Path; - -TYPESYSTEM_SOURCE(Path::PropertyTooltable, App::Property) - -PropertyTooltable::PropertyTooltable() -{ -} - -PropertyTooltable::~PropertyTooltable() -{ -} - -void PropertyTooltable::setValue(const Tooltable& tt) -{ - aboutToSetValue(); - _Tooltable = tt; - hasSetValue(); -} - - -const Tooltable &PropertyTooltable::getValue()const -{ - return _Tooltable; -} - -PyObject *PropertyTooltable::getPyObject() -{ - return new TooltablePy(new Tooltable(_Tooltable)); -} - -void PropertyTooltable::setPyObject(PyObject *value) -{ - if (PyObject_TypeCheck(value, &(TooltablePy::Type))) { - TooltablePy *pcObject = static_cast(value); - setValue(*pcObject->getTooltablePtr()); - } - else { - std::string error = std::string("type must be 'Tooltable', not "); - error += value->ob_type->tp_name; - throw Base::TypeError(error); - } -} - -App::Property *PropertyTooltable::Copy() const -{ - PropertyTooltable *prop = new PropertyTooltable(); - prop->_Tooltable = this->_Tooltable; - - return prop; -} - -void PropertyTooltable::Paste(const App::Property &from) -{ - aboutToSetValue(); - _Tooltable = dynamic_cast(from)._Tooltable; - hasSetValue(); -} - -unsigned int PropertyTooltable::getMemSize () const -{ - return _Tooltable.getMemSize(); -} - -void PropertyTooltable::Save (Base::Writer &writer) const -{ - _Tooltable.Save(writer); -} - -void PropertyTooltable::Restore(Base::XMLReader &reader) -{ - Path::Tooltable temp; - temp.Restore(reader); - setValue(temp); -} - - diff --git a/src/Mod/Path/App/PropertyTooltable.h b/src/Mod/Path/App/PropertyTooltable.h deleted file mode 100644 index 78267ce46f..0000000000 --- a/src/Mod/Path/App/PropertyTooltable.h +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 PROPERTYTOOLTABLE_H -#define PROPERTYTOOLTABLE_H - -#include "Tooltable.h" -#include - -namespace Path -{ - - -/** The tooltable property class. */ -class PathExport PropertyTooltable : public App::Property -{ - TYPESYSTEM_HEADER(); - -public: - PropertyTooltable(); - ~PropertyTooltable(); - - /** @name Getter/setter */ - //@{ - /// set the part shape - void setValue(const Tooltable&); - /// get the part shape - const Tooltable &getValue(void) const; - //@} - - /** @name Python interface */ - //@{ - PyObject* getPyObject(void); - void setPyObject(PyObject *value); - //@} - - /** @name Save/restore */ - //@{ - void Save (Base::Writer &writer) const; - void Restore(Base::XMLReader &reader); - - App::Property *Copy(void) const; - void Paste(const App::Property &from); - unsigned int getMemSize (void) const; - //@} - -private: - Tooltable _Tooltable; -}; - - -} //namespace Path - - -#endif // PROPERTYTOOLTABLE_H diff --git a/src/Mod/Path/App/Tool.cpp b/src/Mod/Path/App/Tool.cpp deleted file mode 100644 index 0e0afda51e..0000000000 --- a/src/Mod/Path/App/Tool.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 "Tool.h" - -using namespace Base; -using namespace Path; - -TYPESYSTEM_SOURCE(Path::Tool , Base::Persistence) - -// Constructors & destructors - -Tool::Tool(const char* name, - ToolType type, - ToolMaterial /*material*/, - double diameter, - double lengthoffset, - double flatradius, - double cornerradius, - double cuttingedgeangle, - double cuttingedgeheight) -:Name(name),Type(type),Material(MATUNDEFINED),Diameter(diameter),LengthOffset(lengthoffset), -FlatRadius(flatradius),CornerRadius(cornerradius),CuttingEdgeAngle(cuttingedgeangle), -CuttingEdgeHeight(cuttingedgeheight) -{ -} - -Tool::Tool() -{ - Type = UNDEFINED; - Material = MATUNDEFINED; - Diameter = 0; - LengthOffset = 0; - FlatRadius = 0; - CornerRadius = 0; - CuttingEdgeAngle = 180; - CuttingEdgeHeight = 0; -} - -Tool::~Tool() -{ -} - -// Reimplemented from base class -unsigned int Tool::getMemSize () const -{ - return 0; -} - -void Tool::Save (Writer &writer) const -{ - writer.Stream() << writer.ind() << "" << std::endl; -} - -void Tool::Restore(XMLReader &reader) -{ - reader.readElement("Tool"); - Name = reader.getAttribute("name"); - Diameter = reader.hasAttribute("diameter") ? (double) reader.getAttributeAsFloat("diameter") : 0.0; - LengthOffset = reader.hasAttribute("length") ? (double) reader.getAttributeAsFloat("length") : 0.0; - FlatRadius = reader.hasAttribute("flat") ? (double) reader.getAttributeAsFloat("flat") : 0.0; - CornerRadius = reader.hasAttribute("corner") ? (double) reader.getAttributeAsFloat("corner") : 0.0; - CuttingEdgeAngle = reader.hasAttribute("angle") ? (double) reader.getAttributeAsFloat("angle") : 180.0; - CuttingEdgeHeight = reader.hasAttribute("height") ? (double) reader.getAttributeAsFloat("height") : 0.0; - std::string type = reader.hasAttribute("type") ? reader.getAttribute("type") : ""; - std::string mat = reader.hasAttribute("mat") ? reader.getAttribute("mat") : ""; - - Type = getToolType(type); - Material = getToolMaterial(mat); - - -} - -const std::vector Tool::ToolTypes() -{ - std::vector toolTypes(13); - toolTypes[0] ="EndMill"; - toolTypes[1] ="Drill"; - toolTypes[2] ="CenterDrill"; - toolTypes[3] ="CounterSink"; - toolTypes[4] ="CounterBore"; - toolTypes[5] ="FlyCutter"; - toolTypes[6] ="Reamer"; - toolTypes[7] ="Tap"; - toolTypes[8] ="SlotCutter"; - toolTypes[9] ="BallEndMill"; - toolTypes[10] ="ChamferMill"; - toolTypes[11] ="CornerRound"; - toolTypes[12] ="Engraver"; - return toolTypes; - -} - -const std::vector Tool::ToolMaterials() -{ - std::vector toolMat(7); - toolMat[0] ="Carbide"; - toolMat[1] ="HighSpeedSteel"; - toolMat[2] ="HighCarbonToolSteel"; - toolMat[3] ="CastAlloy"; - toolMat[4] ="Ceramics"; - toolMat[5] ="Diamond"; - toolMat[6] ="Sialon"; - return toolMat; - -} - -Tool::ToolType Tool::getToolType(std::string type) -{ - Tool::ToolType Type; - if(type=="EndMill") - Type = Tool::ENDMILL; - else if(type=="Drill") - Type = Tool::DRILL; - else if(type=="CenterDrill") - Type = Tool::CENTERDRILL; - else if(type=="CounterSink") - Type = Tool::COUNTERSINK; - else if(type=="CounterBore") - Type = Tool::COUNTERBORE; - else if(type=="FlyCutter") - Type = Tool::FLYCUTTER; - else if(type=="Reamer") - Type = Tool::REAMER; - else if(type=="Tap") - Type = Tool::TAP; - else if(type=="SlotCutter") - Type = Tool::SLOTCUTTER; - else if(type=="BallEndMill") - Type = Tool::BALLENDMILL; - else if(type=="ChamferMill") - Type = Tool::CHAMFERMILL; - else if(type=="CornerRound") - Type = Tool::CORNERROUND; - else if(type=="Engraver") - Type = Tool::ENGRAVER; - else - Type = Tool::UNDEFINED; - - return Type; -} - -Tool::ToolMaterial Tool::getToolMaterial(std::string mat) -{ - Tool::ToolMaterial Material; - if(mat=="Carbide") - Material = Tool::CARBIDE; - else if(mat=="HighSpeedSteel") - Material = Tool::HIGHSPEEDSTEEL; - else if(mat=="HighCarbonToolSteel") - Material = Tool::HIGHCARBONTOOLSTEEL; - else if(mat=="CastAlloy") - Material = Tool::CASTALLOY; - else if(mat=="Ceramics") - Material = Tool::CERAMICS; - else if(mat=="Diamond") - Material = Tool::DIAMOND; - else if(mat=="Sialon") - Material = Tool::SIALON; - else - Material = Tool::MATUNDEFINED; - - return Material; -} - -const char* Tool::TypeName(Tool::ToolType typ) { - switch (typ) { - case Tool::DRILL: - return "Drill"; - case Tool::CENTERDRILL: - return "CenterDrill"; - case Tool::COUNTERSINK: - return "CounterSink"; - case Tool::COUNTERBORE: - return "CounterBore"; - case Tool::FLYCUTTER: - return "FlyCutter"; - case Tool::REAMER: - return "Reamer"; - case Tool::TAP: - return "Tap"; - case Tool::ENDMILL: - return "EndMill"; - case Tool::SLOTCUTTER: - return "SlotCutter"; - case Tool::BALLENDMILL: - return "BallEndMill"; - case Tool::CHAMFERMILL: - return "ChamferMill"; - case Tool::CORNERROUND: - return "CornerRound"; - case Tool::ENGRAVER: - return "Engraver"; - case Tool::UNDEFINED: - return "Undefined"; - } - return "Undefined"; -} - -const char* Tool::MaterialName(Tool::ToolMaterial mat) -{ - switch (mat) { - case Tool::HIGHSPEEDSTEEL: - return "HighSpeedSteel"; - case Tool::CARBIDE: - return "Carbide"; - case Tool::HIGHCARBONTOOLSTEEL: - return "HighCarbonToolSteel"; - case Tool::CASTALLOY: - return "CastAlloy"; - case Tool::CERAMICS: - return "Ceramics"; - case Tool::DIAMOND: - return "Diamond"; - case Tool::SIALON: - return "Sialon"; - case Tool::MATUNDEFINED: - return "Undefined"; - } - return "Undefined"; -} \ No newline at end of file diff --git a/src/Mod/Path/App/Tool.h b/src/Mod/Path/App/Tool.h deleted file mode 100644 index 7be4d9d857..0000000000 --- a/src/Mod/Path/App/Tool.h +++ /dev/null @@ -1,107 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 PATH_TOOL_H -#define PATH_TOOL_H - -#include -#include -#include -#include -#include - -namespace Path -{ - - /** The representation of a single tool */ - class PathExport Tool : public Base::Persistence - { - TYPESYSTEM_HEADER(); - - public: - enum ToolType { - UNDEFINED, - DRILL, - CENTERDRILL, - COUNTERSINK, - COUNTERBORE, - FLYCUTTER, - REAMER, - TAP, - ENDMILL, - SLOTCUTTER, - BALLENDMILL, - CHAMFERMILL, - CORNERROUND, - ENGRAVER }; - - enum ToolMaterial { - MATUNDEFINED, - HIGHSPEEDSTEEL, - HIGHCARBONTOOLSTEEL, - CASTALLOY, - CARBIDE, - CERAMICS, - DIAMOND, - SIALON }; - - //constructors - Tool(); - Tool(const char* name, - ToolType type=Tool::UNDEFINED, - ToolMaterial material=Tool::MATUNDEFINED, - double diameter=10.0, - double lengthoffset=100, - double flatradius=0, - double cornerradius=0, - double cuttingedgeangle=0, - double cuttingedgeheight=0); - ~Tool(); - - // from base class - virtual unsigned int getMemSize (void) const; - virtual void Save (Base::Writer &/*writer*/) const; - virtual void Restore(Base::XMLReader &/*reader*/); - - // attributes - std::string Name; - ToolType Type; - ToolMaterial Material; - double Diameter; - double LengthOffset; - double FlatRadius; - double CornerRadius; - double CuttingEdgeAngle; - double CuttingEdgeHeight; - - static const std::vector ToolTypes(void); - static const std::vector ToolMaterials(void); - static const char* TypeName(ToolType typ); - static ToolType getToolType(std::string type); - static ToolMaterial getToolMaterial(std::string mat); - static const char* MaterialName(ToolMaterial mat); - }; - - using ToolPtr = std::shared_ptr; -} //namespace Path - -#endif // PATH_TOOL_H diff --git a/src/Mod/Path/App/ToolPy.xml b/src/Mod/Path/App/ToolPy.xml deleted file mode 100644 index c174b7a20b..0000000000 --- a/src/Mod/Path/App/ToolPy.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - The Tool objects holds the properties of a CNC tool. -optional attributes: - name: a user-defined name for this tool - tooltype: Drill, CenterDrill, CounterSink, CounterBore, Reamer, Tap, EndMill, SlotCutter, BallEndMill, ChamferMill, CornerRound, Engraver or Undefined - material: HighSpeedSteel, HighCarbonToolSteel, Carbide, CastAlloy, Ceramics, Diamond, Sialon or Undefined - diameter : the diameter of this tool - lengthOffset - flatRadius - cornerRadius - cuttingEdgeAngle - cuttingEdgeHeight - - - - the name of this tool in mm - - - - - - the type of this tool: Drill, CenterDrill, CounterSink, CounterBore, Reamer, Tap, -EndMill, SlotCutter, BallEndMill, ChamferMill, CornerRound, Engraver or Undefined - - - - - - the material of this tool: Steel, Carbide, HighSpeedSteel, -HighCarbonToolSteel CastAlloy, Ceramics, Diamond, Sialon or Undefined - - - - - - the diameter of this tool in mm - - - - - - the length offset of this tool in mm - - - - - - the flat radius of this tool in mm - - - - - - the corner radius of this tool in mm - - - - - - the cutting edge angle of this tool - - - - - - the cutting edge height of this tool in mm - - - - - - returns a copy of this tool - - - - - returns all available tool types - - - - - returns all available tool materials - - - - - setFromTemplate(xmlString|dictionary) ... fills receiver with values from the template string or dictionary - - - - - templateAttrs() ... returns a dictionary with all attributes - - - - - diff --git a/src/Mod/Path/App/ToolPyImp.cpp b/src/Mod/Path/App/ToolPyImp.cpp deleted file mode 100644 index 17cfe90d2c..0000000000 --- a/src/Mod/Path/App/ToolPyImp.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 "Base/Reader.h" -#include "Mod/Path/App/Tool.h" -#include "Mod/Path/App/Tooltable.h" - -// inclusion of the generated files (generated out of ToolPy.xml and TooltablePy.xml) -#include "ToolPy.h" -#include "ToolPy.cpp" - -using namespace Path; - -#define PYSTRING_FROMSTRING(str) PyUnicode_FromString(str) -#define PYINT_TYPE PyLong_Type -#define PYINT_FROMLONG(l) PyLong_FromLong(l) -#define PYINT_ASLONG(o) PyLong_AsLong(o) - - -// returns a string which represents the object e.g. when printed in python -std::string ToolPy::representation() const -{ - std::stringstream str; - str.precision(5); - str << "Tool "; - str << getToolPtr()->Name; - return str.str(); -} - -PyObject *ToolPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper -{ - // create a new instance of ToolPy and the Twin object - return new ToolPy(new Tool); -} - -// constructor method -int ToolPy::PyInit(PyObject* args, PyObject* kwd) -{ - char *name="Default tool"; - char *type = "Undefined"; - char *mat = "Undefined"; - PyObject *dia = nullptr; - PyObject *len = nullptr; - PyObject *fla = nullptr; - PyObject *cor = nullptr; - PyObject *ang = nullptr; - PyObject *hei = nullptr; - int version = 1; - - static char *kwlist[] = {"name", "tooltype", "material", "diameter", "lengthOffset", "flatRadius", "cornerRadius", "cuttingEdgeAngle", "cuttingEdgeHeight" , "version", nullptr}; - - PyObject *dict = nullptr; - if (!kwd && (PyObject_TypeCheck(args, &PyDict_Type) || PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))) { - static PyObject *arg = PyTuple_New(0); - if (PyObject_TypeCheck(args, &PyDict_Type)) { - dict = args; - } - if (!PyArg_ParseTupleAndKeywords(arg, dict, "|sssOOOOOOi", kwlist, &name, &type, &mat, &dia, &len, &fla, &cor, &ang, &hei, &version)) { - return -1; - } - } else { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwd, "|sssOOOOOO", kwlist, &name, &type, &mat, &dia, &len, &fla, &cor, &ang, &hei)) { - return -1; - } - } - - if (1 != version) { - PyErr_SetString(PyExc_TypeError, "Unsupported Tool template version"); - return -1; - } - - getToolPtr()->Name = name; - - std::string typeStr(type); - getToolPtr()->Type = Tool::getToolType(typeStr); - - std::string matStr(mat); - getToolPtr()->Material = Tool::getToolMaterial(matStr); - - getToolPtr()->Diameter = dia ? PyFloat_AsDouble(dia) : 0.0; - getToolPtr()->LengthOffset = len ? PyFloat_AsDouble(len) : 0.0; - getToolPtr()->FlatRadius = fla ? PyFloat_AsDouble(fla) : 0.0; - getToolPtr()->CornerRadius = cor ? PyFloat_AsDouble(cor) : 0.0; - getToolPtr()->CuttingEdgeAngle = ang ? PyFloat_AsDouble(ang) : 180.0; - getToolPtr()->CuttingEdgeHeight = hei ? PyFloat_AsDouble(hei) : 0.0; - - return 0; -} - -// attributes get/setters - -Py::String ToolPy::getName() const -{ - return Py::String(getToolPtr()->Name.c_str()); -} - -void ToolPy::setName(Py::String arg) -{ - std::string name = arg.as_std_string(); - getToolPtr()->Name = name; -} - -Py::String ToolPy::getToolType() const -{ - return Py::String(Tool::TypeName(getToolPtr()->Type)); -} - -void ToolPy::setToolType(Py::String arg) -{ - std::string typeStr(arg.as_std_string()); - getToolPtr()->Type = Tool::getToolType(typeStr); - -} - -Py::String ToolPy::getMaterial() const -{ - return Py::String(Tool::MaterialName(getToolPtr()->Material)); -} - -void ToolPy::setMaterial(Py::String arg) -{ - std::string matStr(arg.as_std_string()); - getToolPtr()->Material = Tool::getToolMaterial(matStr); -} - -Py::Float ToolPy::getDiameter() const -{ - return Py::Float(getToolPtr()->Diameter); -} - -void ToolPy::setDiameter(Py::Float arg) -{ - getToolPtr()->Diameter = arg.operator double(); -} - -Py::Float ToolPy::getLengthOffset() const -{ - return Py::Float(getToolPtr()->LengthOffset); -} - -void ToolPy::setLengthOffset(Py::Float arg) -{ - getToolPtr()->LengthOffset = arg.operator double(); -} - -Py::Float ToolPy::getFlatRadius() const -{ - return Py::Float(getToolPtr()->FlatRadius); -} - -void ToolPy::setFlatRadius(Py::Float arg) -{ - getToolPtr()->FlatRadius = arg.operator double(); -} - -Py::Float ToolPy::getCornerRadius() const -{ - return Py::Float(getToolPtr()->CornerRadius); -} - -void ToolPy::setCornerRadius(Py::Float arg) -{ - getToolPtr()->CornerRadius = arg.operator double(); -} - -Py::Float ToolPy::getCuttingEdgeAngle() const -{ - return Py::Float(getToolPtr()->CuttingEdgeAngle); -} - -void ToolPy::setCuttingEdgeAngle(Py::Float arg) -{ - getToolPtr()->CuttingEdgeAngle = arg.operator double(); -} - -Py::Float ToolPy::getCuttingEdgeHeight() const -{ - return Py::Float(getToolPtr()->CuttingEdgeHeight); -} - -void ToolPy::setCuttingEdgeHeight(Py::Float arg) -{ - getToolPtr()->CuttingEdgeHeight = arg.operator double(); -} - -// custom attributes get/set - -PyObject *ToolPy::getCustomAttributes(const char* /*attr*/) const -{ - return nullptr; -} - -int ToolPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) -{ - return 0; -} - -PyObject* ToolPy::copy(PyObject * args) -{ - if (PyArg_ParseTuple(args, "")) { - return new ToolPy(new Path::Tool(*getToolPtr())); - } - throw Py::TypeError("This method accepts no argument"); -} - -PyObject* ToolPy::setFromTemplate(PyObject * args) -{ - char *pstr = nullptr; - if (PyArg_ParseTuple(args, "s", &pstr)) { - // embed actual string in dummy tag so XMLReader can consume that on construction - std::ostringstream os; - os << "" << pstr << ""; - std::istringstream is(os.str()); - Base::XMLReader reader("", is); - getToolPtr()->Restore(reader); - Py_Return ; - } - - PyErr_Clear(); - if (!PyInit(args, nullptr)) { - Py_Return ; - } - - PyErr_SetString(PyExc_TypeError, "argument must be a string or dictionary"); - return nullptr; -} - -PyObject* ToolPy::templateAttrs(PyObject * args) -{ - if (!args || PyArg_ParseTuple(args, "")) { - PyObject *dict = PyDict_New(); - PyDict_SetItemString(dict, "version", PYINT_FROMLONG(1)); - PyDict_SetItemString(dict, "name", PYSTRING_FROMSTRING(getToolPtr()->Name.c_str())); - PyDict_SetItemString(dict, "tooltype",PYSTRING_FROMSTRING(Tool::TypeName(getToolPtr()->Type))); - PyDict_SetItemString(dict, "material", PYSTRING_FROMSTRING(Tool::MaterialName(getToolPtr()->Material))); - PyDict_SetItemString(dict, "diameter", PyFloat_FromDouble(getToolPtr()->Diameter)); - PyDict_SetItemString(dict, "lengthOffset", PyFloat_FromDouble(getToolPtr()->LengthOffset)); - PyDict_SetItemString(dict, "flatRadius", PyFloat_FromDouble(getToolPtr()->FlatRadius)); - PyDict_SetItemString(dict, "cornerRadius", PyFloat_FromDouble(getToolPtr()->CornerRadius)); - PyDict_SetItemString(dict, "cuttingEdgeAngle", PyFloat_FromDouble(getToolPtr()->CuttingEdgeAngle)); - PyDict_SetItemString(dict, "cuttingEdgeHeight", PyFloat_FromDouble(getToolPtr()->CuttingEdgeHeight)); - return dict; - } - throw Py::TypeError("This method accepts no argument"); -} - -PyObject* ToolPy::getToolTypes(PyObject * args) -{ - if (PyArg_ParseTuple(args, "")) { - std::vector toolTypes = Tool::ToolTypes(); - Py::List list; - for(unsigned i = 0; i != toolTypes.size(); i++) { - - list.append(Py::asObject(PYSTRING_FROMSTRING(toolTypes[i].c_str()))); - } - return Py::new_reference_to(list); - } - throw Py::TypeError("This method accepts no argument"); -} - -PyObject* ToolPy::getToolMaterials(PyObject * args) -{ - if (PyArg_ParseTuple(args, "")) { - std::vector toolMaterials = Tool::ToolMaterials(); - Py::List list;; - for(unsigned i = 0; i != toolMaterials.size(); i++) { - - list.append(Py::asObject(PYSTRING_FROMSTRING(toolMaterials[i].c_str()))); - } - return Py::new_reference_to(list); - } - throw Py::TypeError("This method accepts no argument"); -} diff --git a/src/Mod/Path/App/Tooltable.cpp b/src/Mod/Path/App/Tooltable.cpp deleted file mode 100644 index a7d10877dc..0000000000 --- a/src/Mod/Path/App/Tooltable.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 "Tooltable.h" - -using namespace Base; -using namespace Path; - -TYPESYSTEM_SOURCE(Path::Tooltable , Base::Persistence) - -Tooltable::Tooltable() -{ - Version = 0; -} - -Tooltable::~Tooltable() -{ -} - -void Tooltable::addTool(const Tool &tool) -{ - ToolPtr tmp = std::make_shared(tool); - if (!Tools.empty()) { - int max = 0; - for(std::map::const_iterator i = Tools.begin(); i != Tools.end(); ++i) { - int k = i->first; - if (k > max) - max = k; - } - Tools[max+1]= tmp; - } else - Tools[1] = tmp; -} - -void Tooltable::setTool(const Tool &tool, int pos) -{ - if (pos == -1) { - addTool(tool); - } else { - ToolPtr tmp = std::make_shared(tool); - Tools[pos] = tmp; - } -} - -void Tooltable::deleteTool(int pos) -{ - if (Tools.find(pos) != Tools.end()) { - Tools.erase(pos); - } else { - throw Base::IndexError("Index not found"); - } -} - -unsigned int Tooltable::getMemSize () const -{ - return 0; -} - -void Tooltable::Save (Writer &writer) const -{ - writer.Stream() << writer.ind() << "" << std::endl; - writer.incInd(); - for(std::map::const_iterator i = Tools.begin(); i != Tools.end(); ++i) { - int k = i->first; - ToolPtr v = i->second; - writer.Stream() << writer.ind() << "" << std::endl; - writer.incInd(); - v->Save(writer); - writer.decInd(); - writer.Stream() << writer.ind() << "" << std::endl; - } - writer.decInd(); - writer.Stream() << writer.ind() << "" << std::endl ; - -} - -void Tooltable::Restore (XMLReader &reader) -{ - Tools.clear(); - reader.readElement("Tooltable"); - int count = reader.getAttributeAsInteger("count"); - for (int i = 0; i < count; i++) { - reader.readElement("Toolslot"); - int id = reader.getAttributeAsInteger("number"); - ToolPtr tmp = std::make_shared(); - tmp->Restore(reader); - Tools[id] = tmp; - } -} diff --git a/src/Mod/Path/App/Tooltable.h b/src/Mod/Path/App/Tooltable.h deleted file mode 100644 index bdfbe27fba..0000000000 --- a/src/Mod/Path/App/Tooltable.h +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 PATH_TOOLTABLE_H -#define PATH_TOOLTABLE_H - -#include -#include -#include -#include -#include "Tool.h" - -namespace Path -{ /** The representation of a table of tools */ - class PathExport Tooltable : public Base::Persistence - { - TYPESYSTEM_HEADER(); - - public: - //constructors - Tooltable(); - ~Tooltable(); - - // from base class - virtual unsigned int getMemSize (void) const; - virtual void Save (Base::Writer &/*writer*/) const; - virtual void Restore(Base::XMLReader &/*reader*/); - - // new functions - void addTool(const Tool &tool); // adds a tool at the end - void setTool(const Tool &tool, int); // inserts a tool - void deleteTool(int); // deletes a tool - - // auto - unsigned int getSize(void) const {return Tools.size();} - const Tool &getTool(int pos) {return *Tools.at(pos);} - const std::map &getTools(void) const {return Tools;} - bool hasTool(int pos) const {return (Tools.count(pos) != 0);} - - // attributes - std::map Tools; - int Version; - std::string Name; - }; - -} //namespace Path - -#endif // PATH_TOOLTABLE_H diff --git a/src/Mod/Path/App/TooltablePy.xml b/src/Mod/Path/App/TooltablePy.xml deleted file mode 100644 index 3549a508e0..0000000000 --- a/src/Mod/Path/App/TooltablePy.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - The Tooltable object holds a table of CNC tools - - - - the name of this tool table - - - - - - the version of this tooltable - - - - - - the dictionary of tools of this table - - - - - - returns a copy of this tooltable - - - - - adds a tool or a list of tools at the end of the table - - - - - getTool(int): -returns the tool found at the given position, or None - - - - - setTool(int,tool): -adds a tool at the given position - - - - - deleteTool(int): -deletes the tool found at the given position - - - - - - setFromTemplate(dict) ... restores receiver from given template attribute dictionary - - - - - templateAttrs() ... returns a dictionary representing the receivers attributes for a template - - - - diff --git a/src/Mod/Path/App/TooltablePyImp.cpp b/src/Mod/Path/App/TooltablePyImp.cpp deleted file mode 100644 index 42b319e8ba..0000000000 --- a/src/Mod/Path/App/TooltablePyImp.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2014 Yorik van Havre * - * * - * 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 "Base/Reader.h" -#include "Mod/Path/App/Tool.h" -#include "Mod/Path/App/Tooltable.h" - -// inclusion of the generated files (generated out of ToolPy.xml and TooltablePy.xml) -#include "ToolPy.h" -#include "TooltablePy.h" -#include "TooltablePy.cpp" - -using namespace Path; - -#define PYSTRING_FROMSTRING(str) PyUnicode_FromString(str) -#define PYINT_TYPE PyLong_Type -#define PYINT_FROMLONG(l) PyLong_FromLong(l) -#define PYINT_ASLONG(o) PyLong_AsLong(o) - -// returns a string which represents the object e.g. when printed in python -std::string TooltablePy::representation() const -{ - std::stringstream str; - str.precision(5); - str << "Tooltable containing "; - str << getTooltablePtr()->getSize() << " tools"; - return str.str(); -} - -PyObject *TooltablePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper -{ - return new TooltablePy(new Tooltable); -} - -// constructor method -int TooltablePy::PyInit(PyObject* args, PyObject* /*kwd*/) -{ - //char *name="Tooltable"; - //int version = 1; - - if (PyArg_ParseTuple(args, "")) { - return 0; - } - PyErr_Clear(); // set by PyArg_ParseTuple() - - PyObject *pcObj; - if (PyArg_ParseTuple(args, "O!", &(PyDict_Type), &pcObj)) { - try { - Py::Dict dict(pcObj); - setTools(dict); - } catch(...) { - PyErr_SetString(PyExc_TypeError, "The dictionary can only contain int:tool pairs"); - return -1; - } - return 0; - } - PyErr_Clear(); // set by PyArg_ParseTuple() - - if (PyArg_ParseTuple(args, "O!", &(PyList_Type), &pcObj)) { - Py::List list(pcObj); - for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Path::ToolPy::Type))) { - Path::Tool &tool = *static_cast((*it).ptr())->getToolPtr(); - getTooltablePtr()->addTool(tool); - } - } - return 0; - } - - PyErr_SetString(PyExc_TypeError, "Argument must be either empty or a list or a dictionary"); - return -1; -} - -// Commands get/set - -Py::Dict TooltablePy::getTools() const -{ - Py::Dict dict; - for(std::map::iterator i = getTooltablePtr()->Tools.begin(); i != getTooltablePtr()->Tools.end(); ++i) { - PyObject *tool = new Path::ToolPy(new Tool(*i->second)); - dict.setItem(Py::Long(i->first), Py::asObject(tool)); - } - return dict; -} - -void TooltablePy::setTools(Py::Dict arg) -{ - getTooltablePtr()->Tools.clear(); - PyObject* dict_copy = PyDict_Copy(arg.ptr()); - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(dict_copy, &pos, &key, &value)) { - if ( PyObject_TypeCheck(key,&(PYINT_TYPE)) && ((PyObject_TypeCheck(value, &(Path::ToolPy::Type))) || PyObject_TypeCheck(value, &PyDict_Type))) { - int ckey = (int)PYINT_ASLONG(key); - if (PyObject_TypeCheck(value, &(Path::ToolPy::Type))) { - Path::Tool &tool = *static_cast(value)->getToolPtr(); - getTooltablePtr()->setTool(tool, ckey); - } else { - PyErr_Clear(); - Path::Tool *tool = new Path::Tool; - // The 'pyTool' object must be created on the heap otherwise Python - // will fail to properly track the reference counts and aborts - // in debug mode. - Path::ToolPy* pyTool = new Path::ToolPy(tool); - PyObject* success = pyTool->setFromTemplate(value); - if (!success) { - Py_DECREF(pyTool); - throw Py::Exception(); - } - getTooltablePtr()->setTool(*tool, ckey); - Py_DECREF(pyTool); - Py_DECREF(success); - } - } else { - throw Py::TypeError("The dictionary can only contain int:tool pairs"); - } - } -} - -// specific methods - -PyObject* TooltablePy::copy(PyObject * args) -{ - if (PyArg_ParseTuple(args, "")) { - return new TooltablePy(new Path::Tooltable(*getTooltablePtr())); - } - throw Py::TypeError("This method accepts no argument"); -} - -PyObject* TooltablePy::addTools(PyObject * args) -{ - PyObject* o; - if (PyArg_ParseTuple(args, "O!", &(Path::ToolPy::Type), &o)) { - Path::Tool &tool = *static_cast(o)->getToolPtr(); - getTooltablePtr()->addTool(tool); - //return new TooltablePy(new Path::Tooltable(*getTooltablePtr())); - Py_INCREF(Py_None); - return Py_None; - } - PyErr_Clear(); - if (PyArg_ParseTuple(args, "O!", &(PyList_Type), &o)) { - Py::List list(o); - for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { - if (PyObject_TypeCheck((*it).ptr(), &(Path::ToolPy::Type))) { - Path::Tool &tool = *static_cast((*it).ptr())->getToolPtr(); - getTooltablePtr()->addTool(tool); - } - } - //return new TooltablePy(new Path::Tooltable(*getTooltablePtr())); - Py_INCREF(Py_None); - return Py_None; - } - Py_Error(PyExc_TypeError, "Wrong parameters - tool or list of tools expected"); -} - -PyObject* TooltablePy::setTool(PyObject * args) -{ - PyObject* o; - int pos = -1; - if (PyArg_ParseTuple(args, "iO!", &pos, &(Path::ToolPy::Type), &o)) { - Path::Tool &tool = *static_cast(o)->getToolPtr(); - getTooltablePtr()->setTool(tool,pos); - //return new TooltablePy(new Path::Tooltable(*getTooltablePtr())); - Py_INCREF(Py_None); - return Py_None; - } - Py_Error(PyExc_TypeError, "Wrong parameters - expected tool and optional integer"); -} - -PyObject* TooltablePy::getTool(PyObject * args) -{ - int pos = -1; - if (PyArg_ParseTuple(args, "i", &pos)) { - if (getTooltablePtr()->hasTool(pos)) - { - Path::Tool tool = getTooltablePtr()->getTool(pos); - return new ToolPy(new Path::Tool(tool)); - } - else - { - Py_INCREF(Py_None); - return Py_None; - } - } - Py_Error(PyExc_TypeError, "Argument must be integer"); -} - -PyObject* TooltablePy::deleteTool(PyObject * args) -{ - int pos = -1; - if (PyArg_ParseTuple(args, "|i", &pos)) { - getTooltablePtr()->deleteTool(pos); - //return new TooltablePy(new Path::Tooltable(*getTooltablePtr())); - Py_INCREF(Py_None); - return Py_None; - } - Py_Error(PyExc_TypeError, "Wrong parameters - expected an integer (optional)"); -} - -// custom attributes get/set - -PyObject *TooltablePy::getCustomAttributes(const char* /*attr*/) const -{ - return nullptr; -} - -int TooltablePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) -{ - return 0; -} - -Py::Int TooltablePy::getVersion() const -{ - return Py::Int(getTooltablePtr()->Version); -} - -void TooltablePy::setVersion(Py::Int version) { - getTooltablePtr()->Version = version; -} - -Py::String TooltablePy::getName() const -{ - return Py::String(getTooltablePtr()->Name.c_str()); -} - -void TooltablePy::setName(Py::String arg) -{ - std::string name = arg.as_std_string(); - getTooltablePtr()->Name = name; -} - -PyObject* TooltablePy::setFromTemplate(PyObject * args) -{ - PyObject *dict = nullptr; - if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict)) { - Py::Dict d(dict); - setTools(d); - Py_Return ; - } - - PyErr_SetString(PyExc_TypeError, "argument must be a dictionary returned from templateAttrs()"); - return nullptr; -} - -PyObject* TooltablePy::templateAttrs(PyObject * args) -{ - (void)args; - PyObject *dict = PyDict_New(); - for(std::map::iterator i = getTooltablePtr()->Tools.begin(); i != getTooltablePtr()->Tools.end(); ++i) { - // The 'tool' object must be created on the heap otherwise Python - // will fail to properly track the reference counts and aborts - // in debug mode. - Path::ToolPy* tool = new Path::ToolPy(new Path::Tool(*i->second)); - PyObject *attrs = tool->templateAttrs(nullptr); - PyDict_SetItem(dict, PYINT_FROMLONG(i->first), attrs); - Py_DECREF(tool); - } - return dict; -} - diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index c6899e5e54..6383353c35 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -10,8 +10,6 @@ set(Path_Scripts Init.py PathCommands.py TestPathApp.py - PathMachineState.py - PathFeedRate.py ) if(BUILD_GUI) @@ -25,168 +23,210 @@ INSTALL( Mod/Path ) +SET(PathPython_SRCS + Path/__init__.py + Path/Log.py + Path/Geom.py + Path/GuiInit.py + Path/Preferences.py +) + +SET(PathPythonBase_SRCS + Path/Base/__init__.py + Path/Base//Drillable.py + Path/Base/MachineState.py + Path/Base/FeedRate.py + Path/Base/Property.py + Path/Base/PropertyBag.py + Path/Base/SetupSheet.py + Path/Base/SetupSheetOpPrototype.py + Path/Base/Util.py +) + +SET(PathPythonBaseGui_SRCS + Path/Base/Gui/__init__.py + Path/Base/Gui/GetPoint.py + Path/Base/Gui/IconViewProvider.py + Path/Base/Gui/PreferencesAdvanced.py + Path/Base/Gui/PropertyBag.py + Path/Base/Gui/PropertyEditor.py + Path/Base/Gui/SetupSheet.py + Path/Base/Gui/SetupSheetOpPrototype.py + Path/Base/Gui/Util.py +) + +SET(PathPythonDressup_SRCS + Path/Dressup/__init__.py + Path/Dressup/Utils.py + Path/Dressup/Boundary.py + Path/Dressup/Tags.py +) + +SET(PathPythonDressupGui_SRCS + Path/Dressup/Gui/__init__.py + Path/Dressup/Gui/AxisMap.py + Path/Dressup/Gui/Dogbone.py + Path/Dressup/Gui/Dragknife.py + Path/Dressup/Gui/LeadInOut.py + Path/Dressup/Gui/Boundary.py + Path/Dressup/Gui/Preferences.py + Path/Dressup/Gui/RampEntry.py + Path/Dressup/Gui/Tags.py + Path/Dressup/Gui/TagPreferences.py + Path/Dressup/Gui/ZCorrect.py +) + +SET(PathPythonMain_SRCS + Path/Main/__init__.py + Path/Main/Job.py + Path/Main/Stock.py +) + +SET(PathPythonMainGui_SRCS + Path/Main/Gui/__init__.py + Path/Main/Gui/Camotics.py + Path/Main/Gui/Fixture.py + Path/Main/Gui/Inspect.py + Path/Main/Gui/Job.py + Path/Main/Gui/JobCmd.py + Path/Main/Gui/JobDlg.py + Path/Main/Gui/PreferencesJob.py + Path/Main/Gui/Sanity.py + Path/Main/Gui/Simulator.py +) + +SET(PathPythonTools_SRCS + Path/Tool/__init__.py + Path/Tool/Bit.py + Path/Tool/Controller.py +) + +SET(PathPythonToolsGui_SRCS + Path/Tool/Gui/__init__.py + Path/Tool/Gui/Bit.py + Path/Tool/Gui/BitCmd.py + Path/Tool/Gui/BitEdit.py + Path/Tool/Gui/BitLibraryCmd.py + Path/Tool/Gui/BitLibrary.py + Path/Tool/Gui/Controller.py +) + +SET(PathPythonPost_SRCS + Path/Post/__init__.py + Path/Post/Command.py + Path/Post/Processor.py + Path/Post/Utils.py + Path/Post/UtilsArguments.py + Path/Post/UtilsExport.py + Path/Post/UtilsParse.py +) + +SET(PathPythonPostScripts_SRCS + Path/Post/scripts/__init__.py + Path/Post/scripts/centroid_post.py + Path/Post/scripts/comparams_post.py + Path/Post/scripts/dxf_post.py + Path/Post/scripts/dynapath_post.py + Path/Post/scripts/example_pre.py + Path/Post/scripts/fablin_post.py + Path/Post/scripts/fanuc_post.py + Path/Post/scripts/gcode_pre.py + Path/Post/scripts/grbl_post.py + Path/Post/scripts/heidenhain_post.py + Path/Post/scripts/jtech_post.py + Path/Post/scripts/KineticNCBeamicon2_post.py + Path/Post/scripts/linuxcnc_post.py + Path/Post/scripts/mach3_mach4_post.py + Path/Post/scripts/marlin_post.py + Path/Post/scripts/nccad_post.py + Path/Post/scripts/opensbp_post.py + Path/Post/scripts/opensbp_pre.py + Path/Post/scripts/philips_post.py + Path/Post/scripts/refactored_centroid_post.py + Path/Post/scripts/refactored_grbl_post.py + Path/Post/scripts/refactored_linuxcnc_post.py + Path/Post/scripts/refactored_mach3_mach4_post.py + Path/Post/scripts/refactored_test_post.py + Path/Post/scripts/rml_post.py + Path/Post/scripts/rrf_post.py + Path/Post/scripts/slic3r_pre.py + Path/Post/scripts/smoothie_post.py + Path/Post/scripts/uccnc_post.py +) + +SET(PathPythonOp_SRCS + Path/Op/__init__.py + Path/Op/Adaptive.py + Path/Op/Area.py + Path/Op/Base.py + Path/Op/CircularHoleBase.py + Path/Op/Custom.py + Path/Op/Deburr.py + Path/Op/Engrave.py + Path/Op/EngraveBase.py + Path/Op/FeatureExtension.py + Path/Op/Drilling.py + Path/Op/Helix.py + Path/Op/MillFace.py + Path/Op/Pocket.py + Path/Op/PocketBase.py + Path/Op/PocketShape.py + Path/Op/Probe.py + Path/Op/Profile.py + Path/Op/Slot.py + Path/Op/Surface.py + Path/Op/SurfaceSupport.py + Path/Op/ThreadMilling.py + Path/Op/Util.py + Path/Op/Vcarve.py + Path/Op/Waterline.py +) + +SET(PathPythonOpGui_SRCS + Path/Op/Gui/__init__.py + Path/Op/Gui/Adaptive.py + Path/Op/Gui/Array.py + Path/Op/Gui/Base.py + Path/Op/Gui/CircularHoleBase.py + Path/Op/Gui/Comment.py + Path/Op/Gui/Copy.py + Path/Op/Gui/Custom.py + Path/Op/Gui/Deburr.py + Path/Op/Gui/Drilling.py + Path/Op/Gui/Engrave.py + Path/Op/Gui/FeatureExtension.py + Path/Op/Gui/Helix.py + Path/Op/Gui/Hop.py + Path/Op/Gui/MillFace.py + Path/Op/Gui/Pocket.py + Path/Op/Gui/PocketBase.py + Path/Op/Gui/PocketShape.py + Path/Op/Gui/Probe.py + Path/Op/Gui/Profile.py + Path/Op/Gui/Selection.py + Path/Op/Gui/SimpleCopy.py + Path/Op/Gui/Slot.py + Path/Op/Gui/Stop.py + Path/Op/Gui/Surface.py + Path/Op/Gui/ThreadMilling.py + Path/Op/Gui/Vcarve.py + Path/Op/Gui/Waterline.py +) + SET(PathScripts_SRCS - PathScripts/drillableLib.py - PathScripts/PathAdaptive.py - PathScripts/PathAdaptiveGui.py - PathScripts/PathAreaOp.py - PathScripts/PathArray.py - PathScripts/PathCircularHoleBase.py - PathScripts/PathCircularHoleBaseGui.py - PathScripts/PathCamoticsGui.py - PathScripts/PathComment.py - PathScripts/PathCopy.py - PathScripts/PathCustom.py - PathScripts/PathCustomGui.py - PathScripts/PathDeburr.py - PathScripts/PathDeburrGui.py - PathScripts/PathDressup.py - PathScripts/PathDressupAxisMap.py - PathScripts/PathDressupDogbone.py - PathScripts/PathDressupDragknife.py - PathScripts/PathDressupHoldingTags.py - PathScripts/PathDressupLeadInOut.py - PathScripts/PathDressupPathBoundary.py - PathScripts/PathDressupPathBoundaryGui.py - PathScripts/PathDressupRampEntry.py - PathScripts/PathDressupTag.py - PathScripts/PathDressupTagGui.py - PathScripts/PathDressupTagPreferences.py - PathScripts/PathDressupZCorrect.py - PathScripts/PathDrilling.py - PathScripts/PathDrillingGui.py - PathScripts/PathEngrave.py - PathScripts/PathEngraveBase.py - PathScripts/PathEngraveGui.py - PathScripts/PathFeatureExtensions.py - PathScripts/PathFeatureExtensionsGui.py - PathScripts/PathFixture.py - PathScripts/PathGeom.py - PathScripts/PathGetPoint.py - PathScripts/PathGui.py - PathScripts/PathGuiInit.py - PathScripts/PathHelix.py - PathScripts/PathHelixGui.py - PathScripts/PathHop.py - PathScripts/PathIconViewProvider.py - PathScripts/PathInspect.py - PathScripts/PathJob.py - PathScripts/PathJobCmd.py - PathScripts/PathJobDlg.py - PathScripts/PathJobGui.py - PathScripts/PathLog.py - PathScripts/PathMillFace.py - PathScripts/PathMillFaceGui.py - PathScripts/PathOp.py - PathScripts/PathOpGui.py - PathScripts/PathOpTools.py - PathScripts/PathPocket.py - PathScripts/PathPocketBase.py - PathScripts/PathPocketBaseGui.py - PathScripts/PathPocketGui.py - PathScripts/PathPocketShape.py - PathScripts/PathPocketShapeGui.py - PathScripts/PathPost.py - PathScripts/PathPostProcessor.py - PathScripts/PathPreferences.py - PathScripts/PathPreferencesAdvanced.py - PathScripts/PathPreferencesPathDressup.py - PathScripts/PathPreferencesPathJob.py - PathScripts/PathProbe.py - PathScripts/PathProbeGui.py - PathScripts/PathProfile.py - PathScripts/PathProfileContour.py - PathScripts/PathProfileContourGui.py - PathScripts/PathProfileEdges.py - PathScripts/PathProfileEdgesGui.py - PathScripts/PathProfileFaces.py - PathScripts/PathProfileFacesGui.py - PathScripts/PathProfileGui.py - PathScripts/PathProperty.py - PathScripts/PathPropertyBag.py - PathScripts/PathPropertyBagGui.py - PathScripts/PathPropertyEditor.py - PathScripts/PathSanity.py - PathScripts/PathSelection.py - PathScripts/PathSetupSheet.py - PathScripts/PathSetupSheetGui.py - PathScripts/PathSetupSheetOpPrototype.py - PathScripts/PathSetupSheetOpPrototypeGui.py - PathScripts/PathSimpleCopy.py - PathScripts/PathSimulatorGui.py - PathScripts/PathSlot.py - PathScripts/PathSlotGui.py - PathScripts/PathStock.py - PathScripts/PathStop.py - PathScripts/PathSurface.py - PathScripts/PathSurfaceGui.py - PathScripts/PathSurfaceSupport.py - PathScripts/PathThreadMilling.py - PathScripts/PathThreadMillingGui.py - PathScripts/PathToolBit.py - PathScripts/PathToolBitCmd.py - PathScripts/PathToolBitEdit.py - PathScripts/PathToolBitGui.py - PathScripts/PathToolBitLibraryCmd.py - PathScripts/PathToolBitLibraryGui.py - PathScripts/PathToolController.py - PathScripts/PathToolControllerGui.py - PathScripts/PathToolEdit.py - PathScripts/PathToolLibraryEditor.py - PathScripts/PathToolLibraryManager.py - PathScripts/PathUtil.py PathScripts/PathUtils.py PathScripts/PathUtilsGui.py - PathScripts/PathVcarve.py - PathScripts/PathVcarveGui.py - PathScripts/PathWaterline.py - PathScripts/PathWaterlineGui.py - PathScripts/PostUtils.py - PathScripts/PostUtilsArguments.py - PathScripts/PostUtilsExport.py - PathScripts/PostUtilsParse.py + PathScripts/PathPropertyBag.py + PathScripts/PathPropertyBagGui.py PathScripts/__init__.py ) -SET(Generator_SRCS - Generators/drill_generator.py - Generators/helix_generator.py - Generators/rotation_generator.py - Generators/threadmilling_generator.py - Generators/toolchange_generator.py -) - -SET(PathScripts_post_SRCS - PathScripts/post/__init__.py - PathScripts/post/centroid_post.py - PathScripts/post/comparams_post.py - PathScripts/post/dxf_post.py - PathScripts/post/dynapath_post.py - PathScripts/post/example_pre.py - PathScripts/post/fablin_post.py - PathScripts/post/fanuc_post.py - PathScripts/post/gcode_pre.py - PathScripts/post/grbl_post.py - PathScripts/post/heidenhain_post.py - PathScripts/post/jtech_post.py - PathScripts/post/KineticNCBeamicon2_post.py - PathScripts/post/linuxcnc_post.py - PathScripts/post/mach3_mach4_post.py - PathScripts/post/marlin_post.py - PathScripts/post/nccad_post.py - PathScripts/post/opensbp_post.py - PathScripts/post/opensbp_pre.py - PathScripts/post/philips_post.py - PathScripts/post/refactored_centroid_post.py - PathScripts/post/refactored_grbl_post.py - PathScripts/post/refactored_linuxcnc_post.py - PathScripts/post/refactored_mach3_mach4_post.py - PathScripts/post/refactored_test_post.py - PathScripts/post/rml_post.py - PathScripts/post/rrf_post.py - PathScripts/post/slic3r_pre.py - PathScripts/post/smoothie_post.py - PathScripts/post/uccnc_post.py +SET(PathPythonBaseGenerator_SRCS + Path/Base/Generator/drill.py + Path/Base/Generator/helix.py + Path/Base/Generator/rotation.py + Path/Base/Generator/threadmilling.py + Path/Base/Generator/toolchange.py ) SET(PathPythonGui_SRCS @@ -256,7 +296,7 @@ SET(PathTests_SRCS PathTests/TestPathHelpers.py PathTests/TestPathHelixGenerator.py PathTests/TestPathLog.py - PathTests/TestPathOpTools.py + PathTests/TestPathOpUtil.py PathTests/TestPathPost.py PathTests/TestPathPreferences.py PathTests/TestPathPropertyBag.py @@ -265,10 +305,8 @@ SET(PathTests_SRCS PathTests/TestPathToolChangeGenerator.py PathTests/TestPathThreadMilling.py PathTests/TestPathThreadMillingGenerator.py - PathTests/TestPathTool.py PathTests/TestPathToolBit.py PathTests/TestPathToolController.py - PathTests/TestPathTooltable.py PathTests/TestPathUtil.py PathTests/TestPathVcarve.py PathTests/TestPathVoronoi.py @@ -313,8 +351,20 @@ SET(Path_Data SET(all_files ${PathScripts_SRCS} - ${Generator_SRCS} - ${PathScripts_post_SRCS} + ${PathPython_SRCS} + ${PathPythonBase_SRCS} + ${PathPythonBaseGui_SRCS} + ${PathPythonBaseGenerator_SRCS} + ${PathPythonDressup_SRCS} + ${PathPythonDressupGui_SRCS} + ${PathPythonMain_SRCS} + ${PathPythonMainGui_SRCS} + ${PathPythonOp_SRCS} + ${PathPythonOpGui_SRCS} + ${PathPythonPost_SRCS} + ${PathPythonPostScripts_SRCS} + ${PathPythonTools_SRCS} + ${PathPythonToolsGui_SRCS} ${PathPythonGui_SRCS} ${Tools_SRCS} ${Tools_Bit_SRCS} @@ -349,9 +399,98 @@ INSTALL( INSTALL( FILES - ${Generator_SRCS} + ${PathPython_SRCS} DESTINATION - Mod/Path/Generators + Mod/Path/Path +) + +INSTALL( + FILES + ${PathPythonBase_SRCS} + DESTINATION + Mod/Path/Path/Base +) + +INSTALL( + FILES + ${PathPythonBaseGenerator_SRCS} + DESTINATION + Mod/Path/Path/Base/Generator +) + +INSTALL( + FILES + ${PathPythonBaseGui_SRCS} + DESTINATION + Mod/Path/Path/Base/Gui +) + +INSTALL( + FILES + ${PathPythonDressup_SRCS} + DESTINATION + Mod/Path/Path/Dressup +) + +INSTALL( + FILES + ${PathPythonDressupGui_SRCS} + DESTINATION + Mod/Path/Path/Dressup/Gui +) + +INSTALL( + FILES + ${PathPythonMain_SRCS} + DESTINATION + Mod/Path/Path/Main +) +INSTALL( + FILES + ${PathPythonMainGui_SRCS} + DESTINATION + Mod/Path/Path/Main/Gui +) + +INSTALL( + FILES + ${PathPythonOp_SRCS} + DESTINATION + Mod/Path/Path/Op +) +INSTALL( + FILES + ${PathPythonOpGui_SRCS} + DESTINATION + Mod/Path/Path/Op/Gui +) + +INSTALL( + FILES + ${PathPythonPost_SRCS} + DESTINATION + Mod/Path/Path/Post +) + +INSTALL( + FILES + ${PathPythonPostScripts_SRCS} + DESTINATION + Mod/Path/Path/Post/scripts +) + +INSTALL( + FILES + ${PathPythonTools_SRCS} + DESTINATION + Mod/Path/Path/Tool +) + +INSTALL( + FILES + ${PathPythonToolsGui_SRCS} + DESTINATION + Mod/Path/Path/Tool/Gui ) INSTALL( @@ -369,13 +508,6 @@ INSTALL( ) -INSTALL( - FILES - ${PathScripts_post_SRCS} - DESTINATION - Mod/Path/PathScripts/post -) - INSTALL( FILES ${PathPythonGui_SRCS} diff --git a/src/Mod/Path/Gui/AppPathGuiPy.cpp b/src/Mod/Path/Gui/AppPathGuiPy.cpp index 54ee0e7bb5..5772dccbd5 100644 --- a/src/Mod/Path/Gui/AppPathGuiPy.cpp +++ b/src/Mod/Path/Gui/AppPathGuiPy.cpp @@ -82,7 +82,7 @@ private: try { std::string path = App::Application::getHomePath(); - path += "Mod/Path/PathScripts/post/"; + path += "Mod/Path/Path/Post/scripts/"; 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()); @@ -113,7 +113,7 @@ private: QFileInfo fileInfo = list.at(i); if (fileInfo.baseName().toStdString() == processor) { if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { - pre << "from PathScripts.post import " << processor; + pre << "from Path.Post.scripts import " << processor; } else { pre << "import " << processor; } @@ -149,7 +149,7 @@ private: try { std::string path = App::Application::getHomePath(); - path += "Mod/Path/PathScripts/post/"; + path += "Mod/Path/Path/Post/scripts/"; 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()); @@ -189,7 +189,7 @@ private: QFileInfo fileInfo = list.at(i); if (fileInfo.baseName().toStdString() == processor) { if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { - pre << "from PathScripts.post import " << processor; + pre << "from Path.Post.scripts import " << processor; } else { pre << "import " << processor; } @@ -225,7 +225,7 @@ private: throw Py::RuntimeError("No object to export"); std::string path = App::Application::getHomePath(); - path += "Mod/Path/PathScripts/post/"; + path += "Mod/Path/Path/Post/scripts/"; 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()); @@ -265,7 +265,7 @@ private: QFileInfo fileInfo = list.at(i); if (fileInfo.baseName().toStdString() == processor) { if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("PathScripts"))) { - pre << "from PathScripts.post import " << processor; + pre << "from Path.Post.scripts import " << processor; } else { pre << "import " << processor; } diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc index 9ef71d6643..18948c1080 100644 --- a/src/Mod/Path/Gui/Resources/Path.qrc +++ b/src/Mod/Path/Gui/Resources/Path.qrc @@ -129,8 +129,6 @@ panels/ToolBitEditor.ui panels/ToolBitLibraryEdit.ui panels/ToolBitSelector.ui - panels/ToolEditor.ui - panels/ToolLibraryEditor.ui panels/TaskPathCamoticsSim.ui panels/TaskPathSimulator.ui panels/ZCorrectEdit.ui diff --git a/src/Mod/Path/Gui/Resources/panels/ToolLibraryEditor.ui b/src/Mod/Path/Gui/Resources/panels/ToolLibraryEditor.ui deleted file mode 100644 index a17c56e007..0000000000 --- a/src/Mod/Path/Gui/Resources/panels/ToolLibraryEditor.ui +++ /dev/null @@ -1,429 +0,0 @@ - - - ToolLibrary - - - - 0 - 0 - 946 - 614 - - - - - 0 - 0 - - - - Tool Library - - - - - - - - Import... - - - - - - - Export... - - - - - - - - - - - - - - 225 - 16777215 - - - - - 0 - - - 0 - - - 6 - - - 0 - - - - - - - Tool Tables - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - - - - 32 - 32 - - - - - - - - :/icons/edit-edit.svg:/icons/edit-edit.svg - - - - - - - - 32 - 32 - - - - - - - - :/icons/list-remove.svg - - - - - - - - - 32 - 32 - - - - - - - - :/icons/list-add.svg - - - - - - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 0 - 0 - - - - false - - - QAbstractItemView::NoDragDrop - - - Qt::IgnoreAction - - - true - - - - 20 - 20 - - - - - - - - - - - false - - - false - - - QAbstractItemView::DragOnly - - - Qt::IgnoreAction - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - false - - - false - - - false - - - false - - - - - - - - - - - New Tool - - - - :/icons/Path_ToolController.svg:/icons/Path_ToolController.svg - - - - - - - false - - - - 0 - 0 - - - - - - - Delete - - - - :/icons/delete.svg:/icons/delete.svg - - - - - - - false - - - false - - - Edit - - - - :/icons/edit-edit.svg:/icons/edit-edit.svg - - - - - - - false - - - false - - - Duplicate - - - - :/icons/Path_ToolDuplicate.svg:/icons/Path_ToolDuplicate.svg - - - - - - - false - - - Move up - - - - :/icons/button_up.svg:/icons/button_up.svg - - - false - - - false - - - false - - - - - - - false - - - false - - - Move down - - - - :/icons/button_down.svg:/icons/button_down.svg - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - false - - - - 0 - 0 - - - - Create Tool Controllers for the selected tools - - - Create Tool Controller(s) - - - - :/icons/Path_LengthOffset.svg:/icons/Path_LengthOffset.svg - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - buttonBox - accepted() - ToolLibrary - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ToolLibrary - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/Mod/Path/Gui/Resources/preferences/PathJob.ui b/src/Mod/Path/Gui/Resources/preferences/PathJob.ui index a930929b31..9f33af9868 100644 --- a/src/Mod/Path/Gui/Resources/preferences/PathJob.ui +++ b/src/Mod/Path/Gui/Resources/preferences/PathJob.ui @@ -633,16 +633,6 @@ Tools - - - - <html><head/><body><p>Legacy Tools have no accurate shape representation and are stored in the user preferences of FreeCAD.</p></body></html> - - - Use Legacy Tools - - - diff --git a/src/Mod/Path/Gui/TaskDlgPathCompound.cpp b/src/Mod/Path/Gui/TaskDlgPathCompound.cpp index a0b9f7aeaf..af741ba7f7 100644 --- a/src/Mod/Path/Gui/TaskDlgPathCompound.cpp +++ b/src/Mod/Path/Gui/TaskDlgPathCompound.cpp @@ -40,9 +40,6 @@ #include #include -#include - - using namespace PathGui; using namespace Gui; diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py index 9fa9b32c52..8e0e6770fc 100644 --- a/src/Mod/Path/InitGui.py +++ b/src/Mod/Path/InitGui.py @@ -59,7 +59,8 @@ class PathWorkbench(Workbench): global PathCommandGroup # Add preferences pages - before loading PathGui to properly order pages of Path group - from PathScripts import PathPreferencesPathJob, PathPreferencesPathDressup + import Path.Dressup.Gui.Preferences as PathPreferencesPathDressup + import Path.Main.Gui.PreferencesJob as PathPreferencesPathJob translate = FreeCAD.Qt.translate @@ -68,9 +69,6 @@ class PathWorkbench(Workbench): PathPreferencesPathDressup.DressupPreferencesPage, "Path" ) - # Check enablement of experimental features - from PathScripts import PathPreferences - # load the builtin modules import Path import PathScripts @@ -79,11 +77,11 @@ class PathWorkbench(Workbench): FreeCADGui.addLanguagePath(":/translations") FreeCADGui.addIconPath(":/icons") - from PathScripts import PathGuiInit - from PathScripts import PathJobCmd + import Path.GuiInit - from PathScripts import PathToolBitCmd - from PathScripts import PathToolBitLibraryCmd + from Path.Main.Gui import JobCmd as PathJobCmd + from Path.Tool.Gui import BitCmd as PathToolBitCmd + from Path.Tool.Gui import BitLibraryCmd as PathToolBitLibraryCmd from PySide.QtCore import QT_TRANSLATE_NOOP @@ -91,7 +89,7 @@ class PathWorkbench(Workbench): import subprocess from packaging.version import Version, parse - PathGuiInit.Startup() + Path.GuiInit.Startup() # build commands list projcmdlist = ["Path_Job", "Path_Post"] @@ -134,12 +132,8 @@ class PathWorkbench(Workbench): # remotecmdlist = ["Path_Remote"] specialcmdlist = [] - if PathPreferences.toolsUseLegacyTools(): - toolcmdlist.append("Path_ToolLibraryEdit") - toolbitcmdlist = [] - else: - toolcmdlist.extend(PathToolBitLibraryCmd.BarList) - toolbitcmdlist = PathToolBitLibraryCmd.MenuList + toolcmdlist.extend(PathToolBitLibraryCmd.BarList) + toolbitcmdlist = PathToolBitLibraryCmd.MenuList engravecmdgroup = ["Path_EngraveTools"] FreeCADGui.addCommand( @@ -151,14 +145,14 @@ class PathWorkbench(Workbench): ) threedcmdgroup = threedopcmdlist - if PathPreferences.experimentalFeaturesEnabled(): + if Path.Preferences.experimentalFeaturesEnabled(): projcmdlist.append("Path_Sanity") prepcmdlist.append("Path_Shape") extracmdlist.extend(["Path_Area", "Path_Area_Workplane"]) specialcmdlist.append("Path_ThreadMilling") twodopcmdlist.append("Path_Slot") - if PathPreferences.advancedOCLFeaturesEnabled(): + if Path.Preferences.advancedOCLFeaturesEnabled(): try: r = subprocess.run( ["camotics", "--version"], capture_output=True, text=True @@ -172,8 +166,8 @@ class PathWorkbench(Workbench): try: import ocl # pylint: disable=unused-variable - from PathScripts import PathSurfaceGui - from PathScripts import PathWaterlineGui + from Path.Op.Gui import Surface + from Path.Op.Gui import Waterline threedopcmdlist.extend(["Path_Surface", "Path_Waterline"]) threedcmdgroup = ["Path_3dTools"] @@ -185,7 +179,7 @@ class PathWorkbench(Workbench): ), ) except ImportError: - if not PathPreferences.suppressOpenCamLibWarning(): + if not Path.Preferences.suppressOpenCamLibWarning(): FreeCAD.Console.PrintError("OpenCamLib is not working!\n") self.appendToolbar(QT_TRANSLATE_NOOP("Workbench", "Project Setup"), projcmdlist) @@ -258,13 +252,13 @@ class PathWorkbench(Workbench): self.dressupcmds = dressupcmdlist - curveAccuracy = PathPreferences.defaultLibAreaCurveAccuracy() + curveAccuracy = Path.Preferences.defaultLibAreaCurveAccuracy() if curveAccuracy: Path.Area.setDefaultParams(Accuracy=curveAccuracy) # keep this one the last entry in the preferences - import PathScripts.PathPreferencesAdvanced as PathPreferencesAdvanced - from PathScripts.PathPreferences import preferences + import Path.Base.Gui.PreferencesAdvanced as PathPreferencesAdvanced + from Path.Preferences import preferences FreeCADGui.addPreferencePage( PathPreferencesAdvanced.AdvancedPreferencesPage, "Path" @@ -272,7 +266,7 @@ class PathWorkbench(Workbench): Log("Loading Path workbench... done\n") # Warn user if current schema doesn't use minute for time in velocity - if not PathPreferences.suppressVelocity(): + if not Path.Preferences.suppressVelocity(): velString = FreeCAD.Units.Quantity( 1, FreeCAD.Units.Velocity ).getUserPreferred()[2][3:] @@ -324,7 +318,7 @@ class PathWorkbench(Workbench): "", ["Path_ExportTemplate"] + self.toolbitctxmenu ) menuAppended = True - if isinstance(obj.Proxy, PathScripts.PathOp.ObjectOp): + if isinstance(obj.Proxy, Path.Op.Base.ObjectOp): self.appendContextMenu( "", ["Path_OperationCopy", "Path_OpActiveToggle"] ) @@ -341,7 +335,7 @@ class PathWorkbench(Workbench): for cmd in self.dressupcmds: self.appendContextMenu("", [cmd]) menuAppended = True - if isinstance(obj.Proxy, PathScripts.PathToolBit.ToolBit): + if isinstance(obj.Proxy, Path.Tool.Bit.ToolBit): self.appendContextMenu("", ["Path_ToolBitSave", "Path_ToolBitSaveAs"]) menuAppended = True if menuAppended: diff --git a/src/Mod/Path/PathScripts/drillableLib.py b/src/Mod/Path/Path/Base/Drillable.py similarity index 85% rename from src/Mod/Path/PathScripts/drillableLib.py rename to src/Mod/Path/Path/Base/Drillable.py index f9c1d8f92c..ea9d4b37fa 100644 --- a/src/Mod/Path/PathScripts/drillableLib.py +++ b/src/Mod/Path/Path/Base/Drillable.py @@ -1,14 +1,14 @@ -import PathScripts.PathLog as PathLog import FreeCAD as App import Part +import Path import numpy import math if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def checkForBlindHole(baseshape, selectedFace): @@ -47,7 +47,7 @@ def isDrillableCylinder(obj, candidate, tooldiameter=None, vector=App.Vector(0, matchToolDiameter = tooldiameter is not None matchVector = vector is not None - PathLog.debug( + Path.Log.debug( "\n match tool diameter {} \n match vector {}".format( matchToolDiameter, matchVector ) @@ -91,28 +91,28 @@ def isDrillableCylinder(obj, candidate, tooldiameter=None, vector=App.Vector(0, raise TypeError("cylinder does not have 3 edges. Not supported yet") if raisedFeature(obj, candidate): - PathLog.debug("The cylindrical face is a raised feature") + Path.Log.debug("The cylindrical face is a raised feature") return False if not matchToolDiameter and not matchVector: return True if matchToolDiameter and tooldiameter / 2 > candidate.Surface.Radius: - PathLog.debug("The tool is larger than the target") + Path.Log.debug("The tool is larger than the target") return False bottomface = checkForBlindHole(obj, candidate) - PathLog.track("candidate is a blind hole") + Path.Log.track("candidate is a blind hole") if ( bottomface is not None and matchVector ): # blind holes only drillable at exact vector result = compareVecs(bottomface.normalAt(0, 0), vector, exact=True) - PathLog.track(result) + Path.Log.track(result) return result elif matchVector and not (compareVecs(getSeam(candidate).Curve.Direction, vector)): - PathLog.debug("The feature is not aligned with the given vector") + Path.Log.debug("The feature is not aligned with the given vector") return False else: return True @@ -124,32 +124,32 @@ def isDrillableFace(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1 """ matchToolDiameter = tooldiameter is not None matchVector = vector is not None - PathLog.debug( + Path.Log.debug( "\n match tool diameter {} \n match vector {}".format( matchToolDiameter, matchVector ) ) if not type(candidate.Surface) == Part.Plane: - PathLog.debug("Drilling on non-planar faces not supported") + Path.Log.debug("Drilling on non-planar faces not supported") return False if ( len(candidate.Edges) == 1 and type(candidate.Edges[0].Curve) == Part.Circle ): # Regular circular face - PathLog.debug("Face is circular - 1 edge") + Path.Log.debug("Face is circular - 1 edge") edge = candidate.Edges[0] elif ( len(candidate.Edges) == 2 and type(candidate.Edges[0].Curve) == Part.Circle and type(candidate.Edges[1].Curve) == Part.Circle ): # process a donut - PathLog.debug("Face is a donut - 2 edges") + Path.Log.debug("Face is a donut - 2 edges") e1 = candidate.Edges[0] e2 = candidate.Edges[1] edge = e1 if e1.Curve.Radius < e2.Curve.Radius else e2 else: - PathLog.debug( + Path.Log.debug( "expected a Face with one or two circular edges got a face with {} edges".format( len(candidate.Edges) ) @@ -157,13 +157,13 @@ def isDrillableFace(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1 return False if vector is not None: # Check for blind hole alignment if not compareVecs(candidate.normalAt(0, 0), vector, exact=True): - PathLog.debug("Vector not aligned") + Path.Log.debug("Vector not aligned") return False if matchToolDiameter and edge.Curve.Radius < tooldiameter / 2: - PathLog.debug("Failed diameter check") + Path.Log.debug("Failed diameter check") return False else: - PathLog.debug("Face is drillable") + Path.Log.debug("Face is drillable") return True @@ -174,7 +174,7 @@ def isDrillableEdge(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1 matchToolDiameter = tooldiameter is not None matchVector = vector is not None - PathLog.debug( + Path.Log.debug( "\n match tool diameter {} \n match vector {}".format( matchToolDiameter, matchVector ) @@ -182,22 +182,22 @@ def isDrillableEdge(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1 edge = candidate if not (isinstance(edge.Curve, Part.Circle) and edge.isClosed()): - PathLog.debug("expected a closed circular edge") + Path.Log.debug("expected a closed circular edge") return False if not hasattr(edge.Curve, "Radius"): - PathLog.debug("The Feature edge has no radius - Ellipse.") + Path.Log.debug("The Feature edge has no radius - Ellipse.") return False if not matchToolDiameter and not matchVector: return True if matchToolDiameter and tooldiameter / 2 > edge.Curve.Radius: - PathLog.debug("The tool is larger than the target") + Path.Log.debug("The tool is larger than the target") return False if matchVector and not (compareVecs(edge.Curve.Axis, vector)): - PathLog.debug("The feature is not aligned with the given vector") + Path.Log.debug("The feature is not aligned with the given vector") return False else: return True @@ -220,7 +220,7 @@ def isDrillable(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1)): vector=App.Vector or None """ - PathLog.debug( + Path.Log.debug( "obj: {} candidate: {} tooldiameter {} vector {}".format( obj, candidate, tooldiameter, vector ) @@ -247,7 +247,7 @@ def isDrillable(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1)): return False except TypeError as e: - PathLog.debug(e) + Path.Log.debug(e) return False # raise TypeError("{}".format(e)) @@ -261,7 +261,7 @@ def compareVecs(vec1, vec2, exact=False): angle = vec1.getAngle(vec2) angle = 0 if math.isnan(angle) else math.degrees(angle) - PathLog.debug("vector angle: {}".format(angle)) + Path.Log.debug("vector angle: {}".format(angle)) if exact: return numpy.isclose(angle, 0, rtol=1e-05, atol=1e-06) else: @@ -285,7 +285,7 @@ def getDrillableTargets(obj, ToolDiameter=None, vector=App.Vector(0, 0, 1)): results = [] for i in range(1, len(shp.Faces)): fname = "Face{}".format(i) - PathLog.debug(fname) + Path.Log.debug(fname) candidate = obj.getSubObject(fname) if not isinstance(candidate.Surface, Part.Cylinder): @@ -295,9 +295,9 @@ def getDrillableTargets(obj, ToolDiameter=None, vector=App.Vector(0, 0, 1)): drillable = isDrillable( shp, candidate, tooldiameter=ToolDiameter, vector=vector ) - PathLog.debug("fname: {} : drillable {}".format(fname, drillable)) + Path.Log.debug("fname: {} : drillable {}".format(fname, drillable)) except Exception as e: - PathLog.debug(e) + Path.Log.debug(e) continue if drillable: diff --git a/src/Mod/Path/PathFeedRate.py b/src/Mod/Path/Path/Base/FeedRate.py similarity index 85% rename from src/Mod/Path/PathFeedRate.py rename to src/Mod/Path/Path/Base/FeedRate.py index ad151342db..b3c150fb85 100644 --- a/src/Mod/Path/PathFeedRate.py +++ b/src/Mod/Path/Path/Base/FeedRate.py @@ -21,11 +21,9 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathLog as PathLog -import PathMachineState -import PathScripts.PathGeom as PathGeom +import Path +import Path.Base.MachineState as PathMachineState import Part -from PathScripts.PathGeom import CmdMoveRapid, CmdMoveAll __title__ = "Feed Rate Helper Utility" __author__ = "sliptonic (Brad Collette)" @@ -37,10 +35,10 @@ TODO: This needs to be able to handle feedrates for axes other than X,Y,Z """ if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def setFeedRate(commandlist, ToolController): @@ -67,26 +65,26 @@ def setFeedRate(commandlist, ToolController): else currentposition.z ) endpoint = FreeCAD.Vector(x, y, z) - if PathGeom.pointsCoincide(currentposition, endpoint): + if Path.Geom.pointsCoincide(currentposition, endpoint): return True - return PathGeom.isVertical(Part.makeLine(currentposition, endpoint)) + return Path.Geom.isVertical(Part.makeLine(currentposition, endpoint)) machine = PathMachineState.MachineState() for command in commandlist: - if command.Name not in CmdMoveAll: + if command.Name not in Path.Geom.CmdMoveAll: continue if _isVertical(machine.getPosition(), command): rate = ( ToolController.VertRapid.Value - if command.Name in CmdMoveRapid + if command.Name in Path.Geom.CmdMoveRapid else ToolController.VertFeed.Value ) else: rate = ( ToolController.HorizRapid.Value - if command.Name in CmdMoveRapid + if command.Name in Path.Geom.CmdMoveRapid else ToolController.HorizFeed.Value ) diff --git a/src/Mod/Path/PathScripts/post/__init__.py b/src/Mod/Path/Path/Base/Generator/__init__.py similarity index 100% rename from src/Mod/Path/PathScripts/post/__init__.py rename to src/Mod/Path/Path/Base/Generator/__init__.py diff --git a/src/Mod/Path/Generators/drill_generator.py b/src/Mod/Path/Path/Base/Generator/drill.py similarity index 90% rename from src/Mod/Path/Generators/drill_generator.py rename to src/Mod/Path/Path/Base/Generator/drill.py index 9b82a4225a..72ebda1b3c 100644 --- a/src/Mod/Path/Generators/drill_generator.py +++ b/src/Mod/Path/Path/Base/Generator/drill.py @@ -21,7 +21,6 @@ # *************************************************************************** -import PathScripts.PathLog as PathLog import Path import numpy @@ -32,10 +31,10 @@ __doc__ = "Generates the drilling toolpath for a single spotshape" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def generate(edge, dwelltime=0.0, peckdepth=0.0, repeat=1, retractheight=None, chipBreak=False): @@ -62,12 +61,12 @@ def generate(edge, dwelltime=0.0, peckdepth=0.0, repeat=1, retractheight=None, c startPoint = edge.Vertexes[0].Point endPoint = edge.Vertexes[1].Point - PathLog.debug(startPoint) - PathLog.debug(endPoint) + Path.Log.debug(startPoint) + Path.Log.debug(endPoint) - PathLog.debug(numpy.isclose(startPoint.sub(endPoint).x, 0, rtol=1e-05, atol=1e-06)) - PathLog.debug(numpy.isclose(startPoint.sub(endPoint).y, 0, rtol=1e-05, atol=1e-06)) - PathLog.debug(endPoint) + Path.Log.debug(numpy.isclose(startPoint.sub(endPoint).x, 0, rtol=1e-05, atol=1e-06)) + Path.Log.debug(numpy.isclose(startPoint.sub(endPoint).y, 0, rtol=1e-05, atol=1e-06)) + Path.Log.debug(endPoint) if dwelltime > 0.0 and peckdepth > 0.0: raise ValueError("Peck and Dwell cannot be used together") diff --git a/src/Mod/Path/Generators/helix_generator.py b/src/Mod/Path/Path/Base/Generator/helix.py similarity index 95% rename from src/Mod/Path/Generators/helix_generator.py rename to src/Mod/Path/Path/Base/Generator/helix.py index ecd63d8457..8002dd2760 100644 --- a/src/Mod/Path/Generators/helix_generator.py +++ b/src/Mod/Path/Path/Base/Generator/helix.py @@ -23,7 +23,6 @@ from numpy import ceil, linspace, isclose import Path -import PathScripts.PathLog as PathLog __title__ = "Helix Path Generator" __author__ = "sliptonic (Brad Collette)" @@ -32,11 +31,11 @@ __doc__ = "Generates the helix for a single spot targetshape" __contributors__ = "russ4262 (Russell Johnson), Lorenz Hüdepohl" -if True: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) +if False: + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def generate( @@ -56,7 +55,7 @@ def generate( startPoint = edge.Vertexes[0].Point endPoint = edge.Vertexes[1].Point - PathLog.track( + Path.Log.track( "(helix: <{}, {}>\n hole radius {}\n inner radius {}\n step over {}\n start point {}\n end point {}\n step_down {}\n tool diameter {}\n direction {}\n startAt {})".format( startPoint.x, startPoint.y, @@ -121,7 +120,7 @@ def generate( raise ValueError("start point is below end point") if hole_radius <= tool_diameter: - PathLog.debug("(single helix mode)\n") + Path.Log.debug("(single helix mode)\n") radii = [hole_radius - tool_diameter / 2] if radii[0] <= 0: raise ValueError( @@ -132,7 +131,7 @@ def generate( outer_radius = hole_radius else: # inner_radius > 0: - PathLog.debug("(annulus mode / full hole)\n") + Path.Log.debug("(annulus mode / full hole)\n") outer_radius = hole_radius - tool_diameter / 2 step_radius = inner_radius + tool_diameter / 2 if abs((outer_radius - step_radius) / step_over_distance) < 1e-5: @@ -141,7 +140,7 @@ def generate( nr = max(int(ceil((outer_radius - inner_radius) / step_over_distance)), 2) radii = linspace(outer_radius, step_radius, nr) - PathLog.debug("Radii: {}".format(radii)) + Path.Log.debug("Radii: {}".format(radii)) # calculate the number of full and partial turns required # Each full turn is two 180 degree arcs. Zsteps is equally spaced step # down values diff --git a/src/Mod/Path/Generators/rotation_generator.py b/src/Mod/Path/Path/Base/Generator/rotation.py similarity index 92% rename from src/Mod/Path/Generators/rotation_generator.py rename to src/Mod/Path/Path/Base/Generator/rotation.py index a2bc44f845..27518a7f87 100644 --- a/src/Mod/Path/Generators/rotation_generator.py +++ b/src/Mod/Path/Path/Base/Generator/rotation.py @@ -25,7 +25,6 @@ # The main generator function should be extended to include other flavors of 3+2 -import PathScripts.PathLog as PathLog import math import Path import FreeCAD @@ -38,10 +37,10 @@ __doc__ = "Generates the rotation toolpath" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class refAxis(Enum): @@ -56,7 +55,7 @@ def relAngle(vec, ref): relative angle. The result is returned in degrees (plus or minus) """ - PathLog.debug("vec: {} ref: {}".format(vec, ref)) + Path.Log.debug("vec: {} ref: {}".format(vec, ref)) norm = vec * 1 # copy vec so we don't alter original if ref == refAxis.x: @@ -72,7 +71,7 @@ def relAngle(vec, ref): rot = FreeCAD.Rotation(norm, ref) ang = math.degrees(rot.Angle) angle = ang * plane.dot(rot.Axis) - PathLog.debug("relative ang: {}".format(angle)) + Path.Log.debug("relative ang: {}".format(angle)) return angle @@ -83,7 +82,7 @@ def __getCRotation(normalVector, cMin=-360, cMax=360): with either the +y or -y axis. multiple poses may be possible. Returns a list of all valid poses """ - PathLog.debug("normalVector: {} cMin: {} cMax: {}".format(normalVector, cMin, cMax)) + Path.Log.debug("normalVector: {} cMin: {} cMax: {}".format(normalVector, cMin, cMax)) angle = relAngle(normalVector, refAxis.y) @@ -152,7 +151,7 @@ def generate(normalVector, aMin=-360, aMax=360, cMin=-360, cMax=360, compound=Fa normalVector = rot.multVec(n """ - PathLog.track( + Path.Log.track( "\n=============\n normalVector: {}\n aMin: {}\n aMax: {}\n cMin: {}\n cMax: {}".format( normalVector, aMin, aMax, cMin, cMax ) @@ -160,7 +159,7 @@ def generate(normalVector, aMin=-360, aMax=360, cMin=-360, cMax=360, compound=Fa # Calculate C rotation cResults = __getCRotation(normalVector, cMin, cMax) - PathLog.debug("C Rotation results {}".format(cResults)) + Path.Log.debug("C Rotation results {}".format(cResults)) solutions = [] for result in cResults: @@ -172,7 +171,7 @@ def generate(normalVector, aMin=-360, aMax=360, cMin=-360, cMax=360, compound=Fa # Get the candidate A rotation for the new vector aResult = __getARotation(newvec, aMin, aMax) - PathLog.debug( + Path.Log.debug( "\n=====\nFor C Rotation: {}\n Calculated A {}\n".format(result, aResult) ) @@ -191,7 +190,7 @@ def generate(normalVector, aMin=-360, aMax=360, cMin=-360, cMax=360, compound=Fa best = solution curlen = testlen - PathLog.debug("best result: {}".format(best)) + Path.Log.debug("best result: {}".format(best)) # format and return rotation commands commands = [] diff --git a/src/Mod/Path/Generators/threadmilling_generator.py b/src/Mod/Path/Path/Base/Generator/threadmilling.py similarity index 93% rename from src/Mod/Path/Generators/threadmilling_generator.py rename to src/Mod/Path/Path/Base/Generator/threadmilling.py index 3694acaac0..2fb0e7bd87 100644 --- a/src/Mod/Path/Generators/threadmilling_generator.py +++ b/src/Mod/Path/Path/Base/Generator/threadmilling.py @@ -24,8 +24,6 @@ from __future__ import print_function import FreeCAD import Path -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog import math from PySide.QtCore import QT_TRANSLATE_NOOP @@ -35,10 +33,10 @@ __url__ = "http://www.freecadweb.org" __doc__ = "Path thread milling operation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -153,7 +151,7 @@ def generate(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, st z = thread.zStart r = -radius i = 0 - while not PathGeom.isRoughly(z, thread.zFinal): + while not Path.Geom.isRoughly(z, thread.zFinal): if thread.overshoots(z): break if 0 == (i & 0x01): @@ -165,7 +163,7 @@ def generate(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, st i = i + 1 z = z + thread.hPitch - if PathGeom.isRoughly(z, thread.zFinal): + if Path.Geom.isRoughly(z, thread.zFinal): x = center.x y = yMin if (i & 0x01) else yMax else: @@ -184,12 +182,12 @@ def generate(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, st a = math.atan2(y - center.y, x - center.x) dx = math.cos(a) * (radius - elevator) dy = math.sin(a) * (radius - elevator) - PathLog.debug("") - PathLog.debug("a={}: dx={:.2f}, dy={:.2f}".format(a / math.pi * 180, dx, dy)) + Path.Log.debug("") + Path.Log.debug("a={}: dx={:.2f}, dy={:.2f}".format(a / math.pi * 180, dx, dy)) elevatorX = x - dx elevatorY = y - dy - PathLog.debug( + Path.Log.debug( "({:.2f}, {:.2f}) -> ({:.2f}, {:.2f})".format(x, y, elevatorX, elevatorY) ) diff --git a/src/Mod/Path/Generators/toolchange_generator.py b/src/Mod/Path/Path/Base/Generator/toolchange.py similarity index 93% rename from src/Mod/Path/Generators/toolchange_generator.py rename to src/Mod/Path/Path/Base/Generator/toolchange.py index e7a6f35b7f..eda14bcb34 100644 --- a/src/Mod/Path/Generators/toolchange_generator.py +++ b/src/Mod/Path/Path/Base/Generator/toolchange.py @@ -21,7 +21,6 @@ # *************************************************************************** -import PathScripts.PathLog as PathLog import Path from enum import Enum @@ -32,10 +31,10 @@ __doc__ = "Generates the rotation toolpath" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class SpindleDirection(Enum): @@ -52,7 +51,7 @@ def generate( """ - PathLog.track( + Path.Log.track( f"toolnumber:{toolnumber} toollabel: {toollabel} spindlespeed:{spindlespeed} spindledirection: {spindledirection}" ) @@ -73,7 +72,7 @@ def generate( else: commands.append(Path.Command(spindledirection.value, {"S": spindlespeed})) - PathLog.track(commands) + Path.Log.track(commands) return commands diff --git a/src/Mod/Path/PathScripts/PathGetPoint.py b/src/Mod/Path/Path/Base/Gui/GetPoint.py similarity index 98% rename from src/Mod/Path/PathScripts/PathGetPoint.py rename to src/Mod/Path/Path/Base/Gui/GetPoint.py index 54e908eae0..1018ffa489 100644 --- a/src/Mod/Path/PathScripts/PathGetPoint.py +++ b/src/Mod/Path/Path/Base/Gui/GetPoint.py @@ -22,7 +22,7 @@ import FreeCAD import FreeCADGui -import PathScripts.PathLog as PathLog +import Path # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -37,8 +37,8 @@ __author__ = "sliptonic (Brad Collette)" __url__ = "https://www.freecadweb.org" __doc__ = "Helper class to use FreeCADGUi.Snapper to let the user enter arbitrary points while the task panel is active." -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.track(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +# Path.Log.track(Path.Log.thisModule()) class TaskPanel: diff --git a/src/Mod/Path/PathScripts/PathIconViewProvider.py b/src/Mod/Path/Path/Base/Gui/IconViewProvider.py similarity index 91% rename from src/Mod/Path/PathScripts/PathIconViewProvider.py rename to src/Mod/Path/Path/Base/Gui/IconViewProvider.py index 5b08e32edb..57ae10e895 100644 --- a/src/Mod/Path/PathScripts/PathIconViewProvider.py +++ b/src/Mod/Path/Path/Base/Gui/IconViewProvider.py @@ -21,9 +21,9 @@ # *************************************************************************** import FreeCAD +import Path +import Path.Base.Util as PathUtil import PathGui -import PathScripts.PathLog as PathLog -import PathScripts.PathUtil as PathUtil import importlib __title__ = "Path Icon ViewProvider" @@ -34,10 +34,10 @@ __doc__ = "ViewProvider who's main and only task is to assign an icon." translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ViewProvider(object): @@ -91,7 +91,7 @@ class ViewProvider(object): self._onEditCallback(False) def setupContextMenu(self, vobj, menu): - PathLog.track() + Path.Log.track() from PySide import QtGui edit = translate("Path", "Edit") @@ -107,12 +107,12 @@ def Attach(vobj, name): """Attach(vobj, name) ... attach the appropriate view provider to the view object. If no view provider was registered for the given name a default IconViewProvider is created.""" - PathLog.track(vobj.Object.Label, name) + Path.Log.track(vobj.Object.Label, name) global _factory for key, value in PathUtil.keyValueIter(_factory): if key == name: return value(vobj, name) - PathLog.track(vobj.Object.Label, name, "PathIconViewProvider") + Path.Log.track(vobj.Object.Label, name, "PathIconViewProvider") return ViewProvider(vobj, name) @@ -120,6 +120,6 @@ def RegisterViewProvider(name, provider): """RegisterViewProvider(name, provider) ... if an IconViewProvider is created for an object with the given name an instance of provider is used instead.""" - PathLog.track(name) + Path.Log.track(name) global _factory _factory[name] = provider diff --git a/src/Mod/Path/PathScripts/PathPreferencesAdvanced.py b/src/Mod/Path/Path/Base/Gui/PreferencesAdvanced.py similarity index 81% rename from src/Mod/Path/PathScripts/PathPreferencesAdvanced.py rename to src/Mod/Path/Path/Base/Gui/PreferencesAdvanced.py index cdac0a8a65..bb1725f483 100644 --- a/src/Mod/Path/PathScripts/PathPreferencesAdvanced.py +++ b/src/Mod/Path/Path/Base/Gui/PreferencesAdvanced.py @@ -21,14 +21,13 @@ # *************************************************************************** import FreeCADGui -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathLog as PathLog +import Path if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class AdvancedPreferencesPage: @@ -38,7 +37,7 @@ class AdvancedPreferencesPage: self.form.EnableAdvancedOCLFeatures.stateChanged.connect(self.updateSelection) def saveSettings(self): - PathPreferences.setPreferencesAdvanced( + Path.Preferences.setPreferencesAdvanced( self.form.EnableAdvancedOCLFeatures.isChecked(), self.form.WarningSuppressAllSpeeds.isChecked(), self.form.WarningSuppressRapidSpeeds.isChecked(), @@ -48,23 +47,23 @@ class AdvancedPreferencesPage: ) def loadSettings(self): - PathLog.track() + Path.Log.track() self.form.WarningSuppressAllSpeeds.setChecked( - PathPreferences.suppressAllSpeedsWarning() + Path.Preferences.suppressAllSpeedsWarning() ) self.form.WarningSuppressRapidSpeeds.setChecked( - PathPreferences.suppressRapidSpeedsWarning(False) + Path.Preferences.suppressRapidSpeedsWarning(False) ) self.form.WarningSuppressSelectionMode.setChecked( - PathPreferences.suppressSelectionModeWarning() + Path.Preferences.suppressSelectionModeWarning() ) self.form.EnableAdvancedOCLFeatures.setChecked( - PathPreferences.advancedOCLFeaturesEnabled() + Path.Preferences.advancedOCLFeaturesEnabled() ) self.form.WarningSuppressOpenCamLib.setChecked( - PathPreferences.suppressOpenCamLibWarning() + Path.Preferences.suppressOpenCamLibWarning() ) - self.form.WarningSuppressVelocity.setChecked(PathPreferences.suppressVelocity()) + self.form.WarningSuppressVelocity.setChecked(Path.Preferences.suppressVelocity()) self.updateSelection() def updateSelection(self, state=None): diff --git a/src/Mod/Path/Path/Base/Gui/PropertyBag.py b/src/Mod/Path/Path/Base/Gui/PropertyBag.py new file mode 100644 index 0000000000..83e52290e0 --- /dev/null +++ b/src/Mod/Path/Path/Base/Gui/PropertyBag.py @@ -0,0 +1,468 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2020 sliptonic * +# * * +# * 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 * +# * * +# *************************************************************************** + +from PySide import QtCore, QtGui +import FreeCAD +import FreeCADGui +import Path +import Path.Base.Gui.IconViewProvider as PathIconViewProvider +import Path.Base.Gui.PropertyEditor as PathPropertyEditor +import Path.Base.PropertyBag as PathPropertyBag +import Path.Base.Util as PathUtil +import re + + +__title__ = "Property Bag Editor" +__author__ = "sliptonic (Brad Collette)" +__url__ = "https://www.freecadweb.org" +__doc__ = "Task panel editor for a PropertyBag" + +if False: + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) +else: + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) + +translate = FreeCAD.Qt.translate + + +class ViewProvider(object): + """ViewProvider for a PropertyBag. + It's sole job is to provide an icon and invoke the TaskPanel on edit.""" + + def __init__(self, vobj, name): + Path.Log.track(name) + vobj.Proxy = self + self.icon = name + # mode = 2 + self.obj = None + self.vobj = None + + def attach(self, vobj): + Path.Log.track() + self.vobj = vobj + self.obj = vobj.Object + + def getIcon(self): + return ":/icons/Path-SetupSheet.svg" + + def __getstate__(self): + return None + + def __setstate__(self, state): + return None + + def getDisplayMode(self, mode): + return "Default" + + def setEdit(self, vobj, mode=0): + Path.Log.track() + taskPanel = TaskPanel(vobj) + FreeCADGui.Control.closeDialog() + FreeCADGui.Control.showDialog(taskPanel) + taskPanel.setupUi() + return True + + def unsetEdit(self, vobj, mode): + FreeCADGui.Control.closeDialog() + return + + def claimChildren(self): + return [] + + def doubleClicked(self, vobj): + self.setEdit(vobj) + + +class Delegate(QtGui.QStyledItemDelegate): + RoleObject = QtCore.Qt.UserRole + 1 + RoleProperty = QtCore.Qt.UserRole + 2 + RoleEditor = QtCore.Qt.UserRole + 3 + + # def paint(self, painter, option, index): + # #Path.Log.track(index.column(), type(option)) + + def createEditor(self, parent, option, index): + editor = PathPropertyEditor.Editor( + index.data(self.RoleObject), index.data(self.RoleProperty) + ) + index.model().setData(index, editor, self.RoleEditor) + return editor.widget(parent) + + def setEditorData(self, widget, index): + Path.Log.track(index.row(), index.column()) + index.data(self.RoleEditor).setEditorData(widget) + + def setModelData(self, widget, model, index): + Path.Log.track(index.row(), index.column()) + editor = index.data(self.RoleEditor) + editor.setModelData(widget) + index.model().setData(index, editor.displayString(), QtCore.Qt.DisplayRole) + + def updateEditorGeometry(self, widget, option, index): + widget.setGeometry(option.rect) + + +class PropertyCreate(object): + def __init__(self, obj, grp, typ, another): + self.obj = obj + self.form = FreeCADGui.PySideUic.loadUi(":panels/PropertyCreate.ui") + + obj.Proxy.refreshCustomPropertyGroups() + for g in sorted(obj.CustomPropertyGroups): + self.form.propertyGroup.addItem(g) + if grp: + self.form.propertyGroup.setCurrentText(grp) + + for t in sorted(PathPropertyBag.SupportedPropertyType): + self.form.propertyType.addItem(t) + if PathPropertyBag.SupportedPropertyType[t] == typ: + typ = t + if typ: + self.form.propertyType.setCurrentText(typ) + else: + self.form.propertyType.setCurrentText("String") + self.form.createAnother.setChecked(another) + + self.form.propertyGroup.currentTextChanged.connect(self.updateUI) + self.form.propertyGroup.currentIndexChanged.connect(self.updateUI) + self.form.propertyName.textChanged.connect(self.updateUI) + self.form.propertyType.currentIndexChanged.connect(self.updateUI) + self.form.propertyEnum.textChanged.connect(self.updateUI) + + def updateUI(self): + + typeSet = True + if self.propertyIsEnumeration(): + self.form.labelEnum.setEnabled(True) + self.form.propertyEnum.setEnabled(True) + typeSet = self.form.propertyEnum.text().strip() != "" + else: + self.form.labelEnum.setEnabled(False) + self.form.propertyEnum.setEnabled(False) + if self.form.propertyEnum.text().strip(): + self.form.propertyEnum.setText("") + + ok = self.form.buttonBox.button(QtGui.QDialogButtonBox.Ok) + + if not re.match("^[A-Za-z0-9_]*$", self.form.propertyName.text()): + typeSet = False + + if typeSet and self.propertyGroup(): + ok.setEnabled(True) + else: + ok.setEnabled(False) + + def propertyName(self): + return self.form.propertyName.text().strip() + + def propertyGroup(self): + return self.form.propertyGroup.currentText().strip() + + def propertyType(self): + return PathPropertyBag.SupportedPropertyType[ + self.form.propertyType.currentText() + ].strip() + + def propertyInfo(self): + return self.form.propertyInfo.toPlainText().strip() + + def createAnother(self): + return self.form.createAnother.isChecked() + + def propertyEnumerations(self): + return [s.strip() for s in self.form.propertyEnum.text().strip().split(",")] + + def propertyIsEnumeration(self): + return self.propertyType() == "App::PropertyEnumeration" + + def exec_(self, name): + if name: + # property exists - this is an edit operation + self.form.propertyName.setText(name) + if self.propertyIsEnumeration(): + self.form.propertyEnum.setText( + ",".join(self.obj.getEnumerationsOfProperty(name)) + ) + self.form.propertyInfo.setText(self.obj.getDocumentationOfProperty(name)) + + self.form.labelName.setEnabled(False) + self.form.propertyName.setEnabled(False) + self.form.labelType.setEnabled(False) + self.form.propertyType.setEnabled(False) + self.form.createAnother.setEnabled(False) + + else: + self.form.propertyName.setText("") + self.form.propertyInfo.setText("") + self.form.propertyEnum.setText("") + # self.form.propertyName.setFocus() + + self.updateUI() + + return self.form.exec_() + + +class TaskPanel(object): + ColumnName = 0 + # ColumnType = 1 + ColumnVal = 1 + # TableHeaders = ['Property', 'Type', 'Value'] + TableHeaders = ["Property", "Value"] + + def __init__(self, vobj): + self.obj = vobj.Object + self.props = sorted(self.obj.Proxy.getCustomProperties()) + self.form = FreeCADGui.PySideUic.loadUi(":panels/PropertyBag.ui") + + # initialized later + self.model = None + self.delegate = None + FreeCAD.ActiveDocument.openTransaction("Edit PropertyBag") + + def updateData(self, topLeft, bottomRight): + pass + + def _setupProperty(self, i, name): + typ = PathPropertyBag.getPropertyTypeName(self.obj.getTypeIdOfProperty(name)) + val = PathUtil.getPropertyValueString(self.obj, name) + info = self.obj.getDocumentationOfProperty(name) + + self.model.setData( + self.model.index(i, self.ColumnName), name, QtCore.Qt.EditRole + ) + # self.model.setData(self.model.index(i, self.ColumnType), typ, QtCore.Qt.EditRole) + self.model.setData( + self.model.index(i, self.ColumnVal), self.obj, Delegate.RoleObject + ) + self.model.setData( + self.model.index(i, self.ColumnVal), name, Delegate.RoleProperty + ) + self.model.setData( + self.model.index(i, self.ColumnVal), val, QtCore.Qt.DisplayRole + ) + + self.model.setData( + self.model.index(i, self.ColumnName), typ, QtCore.Qt.ToolTipRole + ) + # self.model.setData(self.model.index(i, self.ColumnType), info, QtCore.Qt.ToolTipRole) + self.model.setData( + self.model.index(i, self.ColumnVal), info, QtCore.Qt.ToolTipRole + ) + + self.model.item(i, self.ColumnName).setEditable(False) + # self.model.item(i, self.ColumnType).setEditable(False) + + def setupUi(self): + Path.Log.track() + + self.delegate = Delegate(self.form) + self.model = QtGui.QStandardItemModel( + len(self.props), len(self.TableHeaders), self.form + ) + self.model.setHorizontalHeaderLabels(self.TableHeaders) + + for i, name in enumerate(self.props): + self._setupProperty(i, name) + + self.form.table.setModel(self.model) + self.form.table.setItemDelegateForColumn(self.ColumnVal, self.delegate) + self.form.table.resizeColumnsToContents() + + self.model.dataChanged.connect(self.updateData) + self.form.table.selectionModel().selectionChanged.connect(self.propertySelected) + self.form.add.clicked.connect(self.propertyAdd) + self.form.remove.clicked.connect(self.propertyRemove) + self.form.modify.clicked.connect(self.propertyModify) + self.form.table.doubleClicked.connect(self.propertyModifyIndex) + self.propertySelected([]) + + def accept(self): + FreeCAD.ActiveDocument.commitTransaction() + FreeCADGui.ActiveDocument.resetEdit() + FreeCADGui.Control.closeDialog() + FreeCAD.ActiveDocument.recompute() + + def reject(self): + FreeCAD.ActiveDocument.abortTransaction() + FreeCADGui.Control.closeDialog() + FreeCAD.ActiveDocument.recompute() + + def propertySelected(self, selection): + Path.Log.track() + if selection: + self.form.modify.setEnabled(True) + self.form.remove.setEnabled(True) + else: + self.form.modify.setEnabled(False) + self.form.remove.setEnabled(False) + + def addCustomProperty(self, obj, dialog): + name = dialog.propertyName() + typ = dialog.propertyType() + grp = dialog.propertyGroup() + info = dialog.propertyInfo() + if name: + propname = self.obj.Proxy.addCustomProperty(typ, name, grp, info) + if dialog.propertyIsEnumeration(): + setattr(self.obj, name, dialog.propertyEnumerations()) + return (propname, info) + return (None, None) + + def propertyAdd(self): + Path.Log.track() + more = False + grp = None + typ = None + while True: + dialog = PropertyCreate(self.obj, grp, typ, more) + if dialog.exec_(None): + # if we block signals the view doesn't get updated, surprise, surprise + # self.model.blockSignals(True) + name, info = self.addCustomProperty(self.obj, dialog) + if name: + index = 0 + for i in range(self.model.rowCount()): + index = i + if ( + self.model.item(i, self.ColumnName).data(QtCore.Qt.EditRole) + > dialog.propertyName() + ): + break + self.model.insertRows(index, 1) + self._setupProperty(index, name) + self.form.table.selectionModel().setCurrentIndex( + self.model.index(index, 0), QtCore.QItemSelectionModel.Rows + ) + # self.model.blockSignals(False) + more = dialog.createAnother() + else: + more = False + else: + more = False + if not more: + break + + def propertyModifyIndex(self, index): + Path.Log.track(index.row(), index.column()) + row = index.row() + + obj = self.model.item(row, self.ColumnVal).data(Delegate.RoleObject) + nam = self.model.item(row, self.ColumnVal).data(Delegate.RoleProperty) + grp = obj.getGroupOfProperty(nam) + typ = obj.getTypeIdOfProperty(nam) + + dialog = PropertyCreate(self.obj, grp, typ, False) + if dialog.exec_(nam): + val = getattr(obj, nam) + obj.removeProperty(nam) + name, info = self.addCustomProperty(self.obj, dialog) + try: + setattr(obj, nam, val) + except Exception: + # this can happen if the old enumeration value doesn't exist anymore + pass + newVal = PathUtil.getPropertyValueString(obj, nam) + self.model.setData( + self.model.index(row, self.ColumnVal), newVal, QtCore.Qt.DisplayRole + ) + + # self.model.setData(self.model.index(row, self.ColumnType), info, QtCore.Qt.ToolTipRole) + self.model.setData( + self.model.index(row, self.ColumnVal), info, QtCore.Qt.ToolTipRole + ) + + def propertyModify(self): + Path.Log.track() + rows = [] + for index in self.form.table.selectionModel().selectedIndexes(): + row = index.row() + if row in rows: + continue + rows.append(row) + + self.propertyModifyIndex(index) + + def propertyRemove(self): + Path.Log.track() + # first find all rows which need to be removed + rows = [] + for index in self.form.table.selectionModel().selectedIndexes(): + if not index.row() in rows: + rows.append(index.row()) + + # then remove them in reverse order so the indexes of the remaining rows + # to delete are still valid + for row in reversed(sorted(rows)): + self.obj.removeProperty(self.model.item(row).data(QtCore.Qt.EditRole)) + self.model.removeRow(row) + + +def Create(name="PropertyBag"): + """Create(name = 'PropertyBag') ... creates a new setup sheet""" + FreeCAD.ActiveDocument.openTransaction("Create PropertyBag") + pcont = PathPropertyBag.Create(name) + PathIconViewProvider.Attach(pcont.ViewObject, name) + return pcont + + +PathIconViewProvider.RegisterViewProvider("PropertyBag", ViewProvider) + + +class PropertyBagCreateCommand(object): + """Command to create a property container object""" + + def __init__(self): + pass + + def GetResources(self): + return { + "MenuText": translate("Path_PropertyBag", "PropertyBag"), + "ToolTip": translate( + "Path_PropertyBag", + "Creates an object which can be used to store reference properties.", + ), + } + + def IsActive(self): + return not FreeCAD.ActiveDocument is None + + def Activated(self): + sel = FreeCADGui.Selection.getSelectionEx() + obj = Create() + body = None + if sel: + if "PartDesign::Body" == sel[0].Object.TypeId: + body = sel[0].Object + elif hasattr(sel[0].Object, "getParentGeoFeatureGroup"): + body = sel[0].Object.getParentGeoFeatureGroup() + if body: + obj.Label = "Attributes" + group = body.Group + group.append(obj) + body.Group = group + + +if FreeCAD.GuiUp: + FreeCADGui.addCommand("Path_PropertyBag", PropertyBagCreateCommand()) + +FreeCAD.Console.PrintLog("Loading PathPropertyBagGui ... done\n") diff --git a/src/Mod/Path/PathScripts/PathPropertyEditor.py b/src/Mod/Path/Path/Base/Gui/PropertyEditor.py similarity index 96% rename from src/Mod/Path/PathScripts/PathPropertyEditor.py rename to src/Mod/Path/Path/Base/Gui/PropertyEditor.py index 8a88862bd5..05830d9a19 100644 --- a/src/Mod/Path/PathScripts/PathPropertyEditor.py +++ b/src/Mod/Path/Path/Base/Gui/PropertyEditor.py @@ -21,8 +21,8 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype +import Path +import Path.Base.SetupSheetOpPrototype as PathSetupSheetOpPrototype from PySide import QtCore, QtGui @@ -33,10 +33,10 @@ __doc__ = "Task panel editor for Properties" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class _PropertyEditor(object): diff --git a/src/Mod/Path/PathScripts/PathSetupSheetGui.py b/src/Mod/Path/Path/Base/Gui/SetupSheet.py similarity index 92% rename from src/Mod/Path/PathScripts/PathSetupSheetGui.py rename to src/Mod/Path/Path/Base/Gui/SetupSheet.py index 7bc654af45..fd77762490 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheetGui.py +++ b/src/Mod/Path/Path/Base/Gui/SetupSheet.py @@ -22,13 +22,13 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathGui as PathGui -import PathScripts.PathIconViewProvider as PathIconViewProvider -import PathScripts.PathLog as PathLog -import PathScripts.PathSetupSheet as PathSetupSheet -import PathScripts.PathSetupSheetOpPrototypeGui as PathSetupSheetOpPrototypeGui -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Gui.IconViewProvider as PathIconViewProvider +import Path.Base.Gui.SetupSheetOpPrototype as PathSetupSheetOpPrototypeGui +import Path.Base.Gui.Util as PathGuiUtil +import Path.Base.SetupSheet as PathSetupSheet +import Path.Base.Util as PathUtil +import PathGui from PySide import QtCore, QtGui @@ -41,10 +41,10 @@ __doc__ = "Task panel editor for a SetupSheet" LOGLEVEL = False if LOGLEVEL: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ViewProvider: @@ -52,7 +52,7 @@ class ViewProvider: It's sole job is to provide an icon and invoke the TaskPanel on edit.""" def __init__(self, vobj, name): - PathLog.track(name) + Path.Log.track(name) vobj.Proxy = self self.icon = name # mode = 2 @@ -60,7 +60,7 @@ class ViewProvider: self.vobj = None def attach(self, vobj): - PathLog.track() + Path.Log.track() self.vobj = vobj self.obj = vobj.Object @@ -77,7 +77,7 @@ class ViewProvider: return "Default" def setEdit(self, vobj, mode=0): - PathLog.track() + Path.Log.track() taskPanel = TaskPanel(vobj) FreeCADGui.Control.closeDialog() FreeCADGui.Control.showDialog(taskPanel) @@ -106,11 +106,11 @@ class Delegate(QtGui.QStyledItemDelegate): return index.data(self.EditorRole).widget(parent) def setEditorData(self, widget, index): - PathLog.track(index.row(), index.column()) + Path.Log.track(index.row(), index.column()) index.data(self.EditorRole).setEditorData(widget) def setModelData(self, widget, model, index): - PathLog.track(index.row(), index.column()) + Path.Log.track(index.row(), index.column()) editor = index.data(self.EditorRole) editor.setModelData(widget) index.model().setData(index, editor.prop.displayString(), QtCore.Qt.DisplayRole) @@ -150,7 +150,7 @@ class OpTaskPanel: self.model.item(topLeft.row(), 2).setEnabled(isset) def setupUi(self): - PathLog.track() + Path.Log.track() self.delegate = Delegate(self.form) self.model = QtGui.QStandardItemModel(len(self.props), 3, self.form) @@ -242,7 +242,7 @@ class OpsDefaultEditor: def accept(self): if any([op.accept() for op in self.ops]): - PathLog.track() + Path.Log.track() def getFields(self): pass @@ -259,7 +259,7 @@ class OpsDefaultEditor: self.currentOp.form.show() def updateModel(self, recomp=True): - PathLog.track() + Path.Log.track() self.getFields() self.updateUI() if recomp: @@ -324,7 +324,7 @@ class GlobalEditor(object): combo.blockSignals(False) def updateUI(self): - PathLog.track() + Path.Log.track() self.form.setupStartDepthExpr.setText(self.obj.StartDepthExpression) self.form.setupFinalDepthExpr.setText(self.obj.FinalDepthExpression) self.form.setupStepDownExpr.setText(self.obj.StepDownExpression) @@ -337,7 +337,7 @@ class GlobalEditor(object): self.selectInComboBox(self.obj.CoolantMode, self.form.setupCoolantMode) def updateModel(self, recomp=True): - PathLog.track() + Path.Log.track() self.getFields() self.updateUI() if recomp: @@ -347,16 +347,16 @@ class GlobalEditor(object): self.updateUI() def setupUi(self): - self.clearanceHeightOffs = PathGui.QuantitySpinBox( + self.clearanceHeightOffs = PathGuiUtil.QuantitySpinBox( self.form.setupClearanceHeightOffs, self.obj, "ClearanceHeightOffset" ) - self.safeHeightOffs = PathGui.QuantitySpinBox( + self.safeHeightOffs = PathGuiUtil.QuantitySpinBox( self.form.setupSafeHeightOffs, self.obj, "SafeHeightOffset" ) - self.rapidHorizontal = PathGui.QuantitySpinBox( + self.rapidHorizontal = PathGuiUtil.QuantitySpinBox( self.form.setupRapidHorizontal, self.obj, "HorizRapid" ) - self.rapidVertical = PathGui.QuantitySpinBox( + self.rapidVertical = PathGuiUtil.QuantitySpinBox( self.form.setupRapidVertical, self.obj, "VertRapid" ) self.form.setupCoolantMode.addItems(self.obj.CoolantModes) @@ -369,7 +369,7 @@ class TaskPanel: def __init__(self, vobj): self.vobj = vobj self.obj = vobj.Object - PathLog.track(self.obj.Label) + Path.Log.track(self.obj.Label) self.globalForm = FreeCADGui.PySideUic.loadUi(":/panels/SetupGlobal.ui") self.globalEditor = GlobalEditor(self.obj, self.globalForm) self.opsEditor = OpsDefaultEditor(self.obj, None) diff --git a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototypeGui.py b/src/Mod/Path/Path/Base/Gui/SetupSheetOpPrototype.py similarity index 95% rename from src/Mod/Path/PathScripts/PathSetupSheetOpPrototypeGui.py rename to src/Mod/Path/Path/Base/Gui/SetupSheetOpPrototype.py index eefc4083eb..81d7b8fcc3 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototypeGui.py +++ b/src/Mod/Path/Path/Base/Gui/SetupSheetOpPrototype.py @@ -21,8 +21,8 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype +import Path +import Path.Base.SetupSheetOpPrototype as PathSetupSheetOpPrototype from PySide import QtCore, QtGui @@ -35,10 +35,10 @@ __doc__ = "Task panel editor for a SetupSheet" LOGLEVEL = False if LOGLEVEL: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class _PropertyEditor(object): @@ -68,7 +68,7 @@ class _PropertyEnumEditor(_PropertyEditor): """Editor for enumeration values - uses a combo box.""" def widget(self, parent): - PathLog.track(self.prop.name, self.prop.getEnumValues()) + Path.Log.track(self.prop.name, self.prop.getEnumValues()) return QtGui.QComboBox(parent) def setEditorData(self, widget): diff --git a/src/Mod/Path/PathScripts/PathGui.py b/src/Mod/Path/Path/Base/Gui/Util.py similarity index 91% rename from src/Mod/Path/PathScripts/PathGui.py rename to src/Mod/Path/Path/Base/Gui/Util.py index bc825bc2ce..320ac6092f 100644 --- a/src/Mod/Path/PathScripts/PathGui.py +++ b/src/Mod/Path/Path/Base/Gui/Util.py @@ -22,9 +22,8 @@ import FreeCAD import FreeCADGui -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Util as PathUtil from PySide import QtGui, QtCore from PySide import QtCore, QtGui @@ -36,10 +35,10 @@ __doc__ = "A collection of helper and utility functions for the Path GUI." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def populateCombobox(form, enumTups, comboBoxesPropertyMap): @@ -50,7 +49,7 @@ def populateCombobox(form, enumTups, comboBoxesPropertyMap): enumTups = list of (translated_text, data_string) tuples comboBoxesPropertyMap = list of (translated_text, data_string) tuples """ - PathLog.track(enumTups) + Path.Log.track(enumTups) # Load appropriate enumerations in each combobox for cb, prop in comboBoxesPropertyMap: @@ -70,12 +69,12 @@ def updateInputField(obj, prop, widget, onBeforeChange=None): Returns True if a new value was assigned, False otherwise (new value is the same as the current). """ value = widget.property("rawValue") - PathLog.track("value: {}".format(value)) + Path.Log.track("value: {}".format(value)) attr = PathUtil.getProperty(obj, prop) attrValue = attr.Value if hasattr(attr, "Value") else attr isDiff = False - if not PathGeom.isRoughly(attrValue, value): + if not Path.Geom.isRoughly(attrValue, value): isDiff = True else: if hasattr(obj, "ExpressionEngine"): @@ -83,9 +82,9 @@ def updateInputField(obj, prop, widget, onBeforeChange=None): for (prp, expr) in obj.ExpressionEngine: if prp == prop: exprSet = True - PathLog.debug('prop = "expression": {} = "{}"'.format(prp, expr)) + Path.Log.debug('prop = "expression": {} = "{}"'.format(prp, expr)) value = FreeCAD.Units.Quantity(obj.evalExpression(expr)).Value - if not PathGeom.isRoughly(attrValue, value): + if not Path.Geom.isRoughly(attrValue, value): isDiff = True break if exprSet: @@ -97,7 +96,7 @@ def updateInputField(obj, prop, widget, onBeforeChange=None): widget.update() if isDiff: - PathLog.debug( + Path.Log.debug( "updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, attr, value) ) if onBeforeChange: @@ -120,7 +119,7 @@ class QuantitySpinBox(QtCore.QObject): def __init__(self, widget, obj, prop, onBeforeChange=None): super().__init__() - PathLog.track(widget) + Path.Log.track(widget) self.widget = widget self.onBeforeChange = onBeforeChange self.prop = None @@ -150,7 +149,7 @@ class QuantitySpinBox(QtCore.QObject): def attachTo(self, obj, prop=None): """attachTo(obj, prop=None) ... use an existing editor for the given object and property""" - PathLog.track(self.prop, prop) + Path.Log.track(self.prop, prop) self.obj = obj self.prop = prop if obj and prop: @@ -161,21 +160,21 @@ class QuantitySpinBox(QtCore.QObject): self.widget.setProperty("binding", "%s.%s" % (obj.Name, prop)) self.valid = True else: - PathLog.warning("Cannot find property {} of {}".format(prop, obj.Label)) + Path.Log.warning("Cannot find property {} of {}".format(prop, obj.Label)) self.valid = False else: self.valid = False def expression(self): """expression() ... returns the expression if one is bound to the property""" - PathLog.track(self.prop, self.valid) + Path.Log.track(self.prop, self.valid) if self.valid: return self.widget.property("expression") return "" def setMinimum(self, quantity): """setMinimum(quantity) ... set the minimum""" - PathLog.track(self.prop, self.valid) + Path.Log.track(self.prop, self.valid) if self.valid: value = quantity.Value if hasattr(quantity, "Value") else quantity self.widget.setProperty("setMinimum", value) @@ -184,7 +183,7 @@ class QuantitySpinBox(QtCore.QObject): """updateSpinBox(quantity=None) ... update the display value of the spin box. If no value is provided the value of the bound property is used. quantity can be of type Quantity or Float.""" - PathLog.track(self.prop, self.valid, quantity) + Path.Log.track(self.prop, self.valid, quantity) if self.valid: expr = self._hasExpression() @@ -205,7 +204,7 @@ class QuantitySpinBox(QtCore.QObject): def updateProperty(self): """updateProperty() ... update the bound property with the value from the spin box""" - PathLog.track(self.prop, self.valid) + Path.Log.track(self.prop, self.valid) if self.valid: return updateInputField( self.obj, self.prop, self.widget, self.onBeforeChange diff --git a/src/Mod/Path/Path/Base/Gui/__init__.py b/src/Mod/Path/Path/Base/Gui/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathMachineState.py b/src/Mod/Path/Path/Base/MachineState.py similarity index 93% rename from src/Mod/Path/PathMachineState.py rename to src/Mod/Path/Path/Base/MachineState.py index 6c2ff960e6..313dce99d9 100644 --- a/src/Mod/Path/PathMachineState.py +++ b/src/Mod/Path/Path/Base/MachineState.py @@ -26,15 +26,15 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Dataclass to implement a machinestate tracker" __contributors__ = "" -import PathScripts.PathLog as PathLog +import Path import FreeCAD -from PathScripts.PathGeom import CmdMoveRapid, CmdMoveAll, CmdMoveDrill +import Path -if True: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) +if False: + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class MachineState: @@ -92,7 +92,7 @@ class MachineState: self.WCS = command.Name return not oldstate == self.getState() - if command.Name in CmdMoveDrill: + if command.Name in Path.Geom.CmdMoveDrill: oldZ = self.Z for p in command.Parameters: self.__setattr__(p, command.Parameters[p]) diff --git a/src/Mod/Path/PathScripts/PathProperty.py b/src/Mod/Path/Path/Base/Property.py similarity index 97% rename from src/Mod/Path/PathScripts/PathProperty.py rename to src/Mod/Path/Path/Base/Property.py index eea7c61745..e790a0d4df 100644 --- a/src/Mod/Path/PathScripts/PathProperty.py +++ b/src/Mod/Path/Path/Base/Property.py @@ -20,7 +20,7 @@ # * * # *************************************************************************** -import PathScripts.PathLog as PathLog +import Path __title__ = "Property type abstraction for editing purposes" __author__ = "sliptonic (Brad Collette)" @@ -28,8 +28,8 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Prototype objects to allow extraction of setup sheet values and editing." -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +# Path.Log.trackModule(Path.Log.thisModule()) class Property(object): diff --git a/src/Mod/Path/Path/Base/PropertyBag.py b/src/Mod/Path/Path/Base/PropertyBag.py new file mode 100644 index 0000000000..e12122ae7d --- /dev/null +++ b/src/Mod/Path/Path/Base/PropertyBag.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2020 sliptonic * +# * * +# * 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 * +# * * +# *************************************************************************** + +from PySide.QtCore import QT_TRANSLATE_NOOP +import FreeCAD +import Path +import re + +__title__ = "Generic property container to store some values." +__author__ = "sliptonic (Brad Collette)" +__url__ = "https://www.freecadweb.org" +__doc__ = "A generic container for typed properties in arbitrary categories." + +if False: + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) +else: + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) + + +translate = FreeCAD.Qt.translate + + +SupportedPropertyType = { + "Angle": "App::PropertyAngle", + "Bool": "App::PropertyBool", + "Distance": "App::PropertyDistance", + "Enumeration": "App::PropertyEnumeration", + "File": "App::PropertyFile", + "Float": "App::PropertyFloat", + "Integer": "App::PropertyInteger", + "Length": "App::PropertyLength", + "Percent": "App::PropertyPercent", + "String": "App::PropertyString", +} + + +def getPropertyTypeName(o): + for typ in SupportedPropertyType: + if SupportedPropertyType[typ] == o: + return typ + raise IndexError() + + +class PropertyBag(object): + """Property container object.""" + + CustomPropertyGroups = "CustomPropertyGroups" + CustomPropertyGroupDefault = "User" + + def __init__(self, obj): + obj.addProperty( + "App::PropertyStringList", + self.CustomPropertyGroups, + "Base", + QT_TRANSLATE_NOOP("App::Property", "List of custom property groups"), + ) + self.onDocumentRestored(obj) + + def __getstate__(self): + return None + + def __setstate__(self, state): + return None + + def __sanitizePropertyName(self, name): + if len(name) == 0: + return + clean = name[0] + for i in range(1, len(name)): + if name[i] == " ": + clean += name[i + 1].upper() + i += 1 + elif name[i - 1] != " ": + clean += name[i] + return clean + + def onDocumentRestored(self, obj): + self.obj = obj + obj.setEditorMode(self.CustomPropertyGroups, 2) # hide + + def getCustomProperties(self): + """getCustomProperties() ... Return a list of all custom properties created in this container.""" + return [ + p + for p in self.obj.PropertiesList + if self.obj.getGroupOfProperty(p) in self.obj.CustomPropertyGroups + ] + + def addCustomProperty(self, propertyType, name, group=None, desc=None): + """addCustomProperty(propertyType, name, group=None, desc=None) ... adds a custom property and tracks its group.""" + if desc is None: + desc = "" + if group is None: + group = self.CustomPropertyGroupDefault + groups = self.obj.CustomPropertyGroups + + name = self.__sanitizePropertyName(name) + if not re.match("^[A-Za-z0-9_]*$", name): + raise ValueError("Property Name can only contain letters and numbers") + + if not group in groups: + groups.append(group) + self.obj.CustomPropertyGroups = groups + self.obj.addProperty(propertyType, name, group, desc) + return name + + def refreshCustomPropertyGroups(self): + """refreshCustomPropertyGroups() ... removes empty property groups, should be called after deleting properties.""" + customGroups = [] + for p in self.obj.PropertiesList: + group = self.obj.getGroupOfProperty(p) + if group in self.obj.CustomPropertyGroups and not group in customGroups: + customGroups.append(group) + self.obj.CustomPropertyGroups = customGroups + + +def Create(name="PropertyBag"): + obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", name) + obj.Proxy = PropertyBag(obj) + return obj + + +def IsPropertyBag(obj): + """Returns True if the supplied object is a property container (or its Proxy).""" + + if type(obj) == PropertyBag: + return True + if hasattr(obj, "Proxy"): + return IsPropertyBag(obj.Proxy) + return False diff --git a/src/Mod/Path/PathScripts/PathSetupSheet.py b/src/Mod/Path/Path/Base/SetupSheet.py similarity index 95% rename from src/Mod/Path/PathScripts/PathSetupSheet.py rename to src/Mod/Path/Path/Base/SetupSheet.py index 027eea73da..3667fd777e 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheet.py +++ b/src/Mod/Path/Path/Base/SetupSheet.py @@ -21,10 +21,9 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Util as PathUtil +import Path.Base.SetupSheetOpPrototype as PathSetupSheetOpPrototype from PySide.QtCore import QT_TRANSLATE_NOOP __title__ = "Setup Sheet for a Job." @@ -36,10 +35,10 @@ _RegisteredOps: dict = {} if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class Template: @@ -73,20 +72,20 @@ class Template: def _traverseTemplateAttributes(attrs, codec): - PathLog.debug(attrs) + Path.Log.debug(attrs) coded = {} for key, value in PathUtil.keyValueIter(attrs): if type(value) == dict: - PathLog.debug("%s is a dict" % key) + Path.Log.debug("%s is a dict" % key) coded[key] = _traverseTemplateAttributes(value, codec) elif type(value) == list: - PathLog.debug("%s is a list" % key) + Path.Log.debug("%s is a list" % key) coded[key] = [_traverseTemplateAttributes(attr, codec) for attr in value] elif PathUtil.isString(value): - PathLog.debug("%s is a string" % key) + Path.Log.debug("%s is a string" % key) coded[key] = codec(value) else: - PathLog.debug("%s is %s" % (key, type(value))) + Path.Log.debug("%s is %s" % (key, type(value))) coded[key] = value return coded @@ -234,7 +233,7 @@ class SetupSheet: return None def hasDefaultToolRapids(self): - return PathGeom.isRoughly(self.obj.VertRapid.Value, 0) and PathGeom.isRoughly( + return Path.Geom.isRoughly(self.obj.VertRapid.Value, 0) and Path.Geom.isRoughly( self.obj.HorizRapid.Value, 0 ) @@ -394,7 +393,7 @@ class SetupSheet: return list(sorted(ops)) def setOperationProperties(self, obj, opName): - PathLog.track(obj.Label, opName) + Path.Log.track(obj.Label, opName) try: op = _RegisteredOps[opName] for prop in op.properties(): @@ -402,7 +401,7 @@ class SetupSheet: if hasattr(self.obj, propName): setattr(obj, prop, getattr(self.obj, propName)) except Exception: - PathLog.info("SetupSheet has no support for {}".format(opName)) + Path.Log.info("SetupSheet has no support for {}".format(opName)) def onDocumentRestored(self, obj): diff --git a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py b/src/Mod/Path/Path/Base/SetupSheetOpPrototype.py similarity index 89% rename from src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py rename to src/Mod/Path/Path/Base/SetupSheetOpPrototype.py index 0070e9aa72..1634d5a1f6 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py +++ b/src/Mod/Path/Path/Base/SetupSheetOpPrototype.py @@ -20,7 +20,7 @@ # * * # *************************************************************************** -import PathScripts.PathLog as PathLog +import Path __title__ = "Setup Sheet for a Job." __author__ = "sliptonic (Brad Collette)" @@ -28,8 +28,8 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Prototype objects to allow extraction of setup sheet values and editing." -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +# Path.Log.trackModule(Path.Log.thisModule()) class Property(object): @@ -65,11 +65,11 @@ class Property(object): def setupProperty(self, obj, name, category, value): created = False if not hasattr(obj, name): - PathLog.track('add', obj.Name, name, self.propType) + Path.Log.track('add', obj.Name, name, self.propType) obj.addProperty(self.propType, name, category, self.info) self.initProperty(obj, name) created = True - PathLog.track('set', obj.Name, name, value, type(value)) + Path.Log.track('set', obj.Name, name, value, type(value)) setattr(obj, name, value) return created @@ -127,7 +127,11 @@ class PropertyFloat(Property): return "Float" def valueFromString(self, string): - return float(string) + try: + return float(string) + except ValueError: + Path.Log.error(f"{self.category}.{self.name} [{self.propType}] : '{string}'") + raise class PropertyInteger(Property): @@ -135,7 +139,11 @@ class PropertyInteger(Property): return "Integer" def valueFromString(self, string): - return int(string) + try: + return int(string) + except ValueError: + Path.Log.error(f"{self.category}.{self.name} [{self.propType}] : '{string}'") + raise class PropertyPercent(PropertyInteger): @@ -148,7 +156,11 @@ class PropertyBool(Property): return "Bool" def valueFromString(self, string): - return bool(string) + try: + return bool(string) + except ValueError: + Path.Log.error(f"{self.category}.{self.name} [{self.propType}] : '{string}'") + raise class PropertyString(Property): diff --git a/src/Mod/Path/PathScripts/PathUtil.py b/src/Mod/Path/Path/Base/Util.py similarity index 90% rename from src/Mod/Path/PathScripts/PathUtil.py rename to src/Mod/Path/Path/Base/Util.py index 19657f6d83..291a47c340 100644 --- a/src/Mod/Path/PathScripts/PathUtil.py +++ b/src/Mod/Path/Path/Base/Util.py @@ -22,25 +22,25 @@ """ The purpose of this file is to collect some handy functions. The reason they -are not in PathUtils (and there is this confusing naming going on) is that +are not in Path.Base.Utils (and there is this confusing naming going on) is that PathUtils depends on PathJob. Which makes it impossible to use the functions and classes defined there in PathJob. So if you add to this file and think about importing anything from PathScripts -other than PathLog, then it probably doesn't belong here. +other than Path.Log, then it probably doesn't belong here. """ import FreeCAD import six -import PathScripts.PathLog as PathLog +import Path translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def _getProperty(obj, prop): @@ -54,13 +54,13 @@ def _getProperty(obj, prop): attr = getattr(o, name) if o == attr: - PathLog.warning( + Path.Log.warning( translate("PathGui", "%s has no property %s (%s))") % (obj.Label, prop, name) ) return (None, None, None) - # PathLog.debug("found property %s of %s (%s: %s)" % (prop, obj.Label, name, attr)) + # Path.Log.debug("found property %s of %s (%s: %s)" % (prop, obj.Label, name, attr)) return (o, attr, name) @@ -98,18 +98,18 @@ def isValidBaseObject(obj): """isValidBaseObject(obj) ... returns true if the object can be used as a base for a job.""" if hasattr(obj, "getParentGeoFeatureGroup") and obj.getParentGeoFeatureGroup(): # Can't link to anything inside a geo feature group anymore - PathLog.debug("%s is inside a geo feature group" % obj.Label) + Path.Log.debug("%s is inside a geo feature group" % obj.Label) return False if hasattr(obj, "BitBody") and hasattr(obj, "BitShape"): # ToolBit's are not valid base objects return False if obj.TypeId in NotValidBaseTypeIds: - PathLog.debug("%s is blacklisted (%s)" % (obj.Label, obj.TypeId)) + Path.Log.debug("%s is blacklisted (%s)" % (obj.Label, obj.TypeId)) return False if hasattr(obj, "Sheets") or hasattr( obj, "TagText" ): # Arch.Panels and Arch.PanelCut - PathLog.debug("%s is not an Arch.Panel" % (obj.Label)) + Path.Log.debug("%s is not an Arch.Panel" % (obj.Label)) return False import Part diff --git a/src/Mod/Path/Path/Base/__init__.py b/src/Mod/Path/Path/Base/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/PathDressupPathBoundary.py b/src/Mod/Path/Path/Dressup/Boundary.py similarity index 86% rename from src/Mod/Path/PathScripts/PathDressupPathBoundary.py rename to src/Mod/Path/Path/Dressup/Boundary.py index 5a45f60965..9194b0d6d7 100644 --- a/src/Mod/Path/PathScripts/PathDressupPathBoundary.py +++ b/src/Mod/Path/Path/Dressup/Boundary.py @@ -23,18 +23,16 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Path -import PathScripts.PathDressup as PathDressup -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathStock as PathStock -import PathScripts.PathUtil as PathUtil +import Path.Base.Util as PathUtil +import Path.Dressup.Utils as PathDressup +import Path.Main.Stock as PathStock import PathScripts.PathUtils as PathUtils if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -127,8 +125,8 @@ class PathBoundary: self.strG0ZclearanceHeight = None def boundaryCommands(self, begin, end, verticalFeed): - PathLog.track(_vstr(begin), _vstr(end)) - if end and PathGeom.pointsCoincide(begin, end): + Path.Log.track(_vstr(begin), _vstr(end)) + if end and Path.Geom.pointsCoincide(begin, end): return [] cmds = [] if begin.z < self.safeHeight: @@ -152,7 +150,7 @@ class PathBoundary: return None if len(self.baseOp.Path.Commands) == 0: - PathLog.warning("No Path Commands for %s" % self.baseOp.Label) + Path.Log.warning("No Path Commands for %s" % self.baseOp.Label) return [] tc = PathDressup.toolController(self.baseOp) @@ -173,12 +171,12 @@ class PathBoundary: commands = [cmd] lastExit = None for cmd in self.baseOp.Path.Commands[1:]: - if cmd.Name in PathGeom.CmdMoveAll: + if cmd.Name in Path.Geom.CmdMoveAll: if bogusX: bogusX = "X" not in cmd.Parameters if bogusY: bogusY = "Y" not in cmd.Parameters - edge = PathGeom.edgeForCmd(cmd, pos) + edge = Path.Geom.edgeForCmd(cmd, pos) if edge: inside = edge.common(self.boundary).Edges outside = edge.cut(self.boundary).Edges @@ -189,7 +187,7 @@ class PathBoundary: # it's really a shame that one cannot trust the sequence and/or # orientation of edges if 1 == len(inside) and 0 == len(outside): - PathLog.track(_vstr(pos), _vstr(lastExit), " + ", cmd) + Path.Log.track(_vstr(pos), _vstr(lastExit), " + ", cmd) # cmd fully included by boundary if lastExit: if not ( @@ -202,25 +200,25 @@ class PathBoundary: ) lastExit = None commands.append(cmd) - pos = PathGeom.commandEndPoint(cmd, pos) + pos = Path.Geom.commandEndPoint(cmd, pos) elif 0 == len(inside) and 1 == len(outside): - PathLog.track(_vstr(pos), _vstr(lastExit), " - ", cmd) + Path.Log.track(_vstr(pos), _vstr(lastExit), " - ", cmd) # cmd fully excluded by boundary if not lastExit: lastExit = pos - pos = PathGeom.commandEndPoint(cmd, pos) + pos = Path.Geom.commandEndPoint(cmd, pos) else: - PathLog.track( + Path.Log.track( _vstr(pos), _vstr(lastExit), len(inside), len(outside), cmd ) # cmd pierces boundary while inside or outside: - ie = [e for e in inside if PathGeom.edgeConnectsTo(e, pos)] - PathLog.track(ie) + ie = [e for e in inside if Path.Geom.edgeConnectsTo(e, pos)] + Path.Log.track(ie) if ie: e = ie[0] LastPt = e.valueAt(e.LastParameter) - flip = PathGeom.pointsCoincide(pos, LastPt) + flip = Path.Geom.pointsCoincide(pos, LastPt) newPos = e.valueAt(e.FirstParameter) if flip else LastPt # inside edges are taken at this point (see swap of inside/outside # above - so we can just connect the dots ... @@ -232,12 +230,12 @@ class PathBoundary: ) ) lastExit = None - PathLog.track(e, flip) + Path.Log.track(e, flip) if not ( bogusX or bogusY ): # don't insert false paths based on bogus m/c position commands.extend( - PathGeom.cmdsForEdge( + Path.Geom.cmdsForEdge( e, flip, False, @@ -253,13 +251,13 @@ class PathBoundary: oe = [ e for e in outside - if PathGeom.edgeConnectsTo(e, pos) + if Path.Geom.edgeConnectsTo(e, pos) ] - PathLog.track(oe) + Path.Log.track(oe) if oe: e = oe[0] ptL = e.valueAt(e.LastParameter) - flip = PathGeom.pointsCoincide(pos, ptL) + flip = Path.Geom.pointsCoincide(pos, ptL) newPos = ( e.valueAt(e.FirstParameter) if flip else ptL ) @@ -268,7 +266,7 @@ class PathBoundary: outside.remove(e) pos = newPos else: - PathLog.error("huh?") + Path.Log.error("huh?") import Part Part.show(Part.Vertex(pos), "pos") @@ -281,16 +279,16 @@ class PathBoundary: # Eif # Ewhile # Eif - # pos = PathGeom.commandEndPoint(cmd, pos) + # pos = Path.Geom.commandEndPoint(cmd, pos) # Eif else: - PathLog.track("no-move", cmd) + Path.Log.track("no-move", cmd) commands.append(cmd) if lastExit: commands.extend(self.boundaryCommands(lastExit, None, tc.VertFeed.Value)) lastExit = None - PathLog.track(commands) + Path.Log.track(commands) return Path.Path(commands) @@ -301,7 +299,7 @@ def Create(base, name="DressupPathBoundary"): """Create(base, name='DressupPathBoundary') ... creates a dressup limiting base's Path to a boundary.""" if not base.isDerivedFrom("Path::Feature"): - PathLog.error( + Path.Log.error( translate("Path_DressupPathBoundary", "The selected object is not a path") + "\n" ) diff --git a/src/Mod/Path/PathScripts/PathDressupAxisMap.py b/src/Mod/Path/Path/Dressup/Gui/AxisMap.py similarity index 93% rename from src/Mod/Path/PathScripts/PathDressupAxisMap.py rename to src/Mod/Path/Path/Dressup/Gui/AxisMap.py index b5b6b7ab9f..df3271bea5 100644 --- a/src/Mod/Path/PathScripts/PathDressupAxisMap.py +++ b/src/Mod/Path/Path/Dressup/Gui/AxisMap.py @@ -23,18 +23,15 @@ import FreeCAD import Path import math -import PathScripts.PathGeom as PathGeom +import Path.Base.Gui.Util as PathGuiUtil import PathScripts.PathUtils as PathUtils -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog from PySide.QtCore import QT_TRANSLATE_NOOP -from PathScripts.PathGeom import CmdMoveArc if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) if FreeCAD.GuiUp: @@ -89,11 +86,11 @@ class ObjectDressup: currLocation = {"X": 0, "Y": 0, "Z": 0, "F": 0} for p in path: - if p.Name in CmdMoveArc: + if p.Name in Path.Geom.CmdMoveArc: curVec = FreeCAD.Vector( currLocation["X"], currLocation["Y"], currLocation["Z"] ) - arcwire = PathGeom.edgeForCmd(p, curVec) + arcwire = Path.Geom.edgeForCmd(p, curVec) pointlist = arcwire.discretize(Deflection=d) for point in pointlist: newcommand = Path.Command( @@ -118,7 +115,7 @@ class ObjectDressup: if obj.Base.Path: if obj.Base.Path.Commands: pp = obj.Base.Path.Commands - if len([i for i in pp if i.Name in CmdMoveArc]) == 0: + if len([i for i in pp if i.Name in Path.Geom.CmdMoveArc]) == 0: pathlist = pp else: pathlist = self._stripArcs(pp, d) @@ -171,7 +168,7 @@ class TaskPanel: def __init__(self, obj): self.obj = obj self.form = FreeCADGui.PySideUic.loadUi(":/panels/AxisMapEdit.ui") - self.radius = PathGui.QuantitySpinBox(self.form.radius, obj, "Radius") + self.radius = PathGuiUtil.QuantitySpinBox(self.form.radius, obj, "Radius") FreeCAD.ActiveDocument.openTransaction("Edit Dragknife Dress-up") def reject(self): @@ -299,19 +296,19 @@ class CommandPathDressup: # everything ok! FreeCAD.ActiveDocument.openTransaction("Create Dress-up") - FreeCADGui.addModule("PathScripts.PathDressupAxisMap") + FreeCADGui.addModule("Path.Dressup.Gui.AxisMap") FreeCADGui.addModule("PathScripts.PathUtils") FreeCADGui.doCommand( 'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "AxisMapDressup")' ) - FreeCADGui.doCommand("PathScripts.PathDressupAxisMap.ObjectDressup(obj)") + FreeCADGui.doCommand("Path.Dressup.Gui.AxisMap.ObjectDressup(obj)") FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name) FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)") FreeCADGui.doCommand("obj.Base = base") FreeCADGui.doCommand("obj.Radius = 45") FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)") FreeCADGui.doCommand( - "obj.ViewObject.Proxy = PathScripts.PathDressupAxisMap.ViewProviderDressup(obj.ViewObject)" + "obj.ViewObject.Proxy = Path.Dressup.Gui.AxisMap.ViewProviderDressup(obj.ViewObject)" ) FreeCADGui.doCommand( "Gui.ActiveDocument.getObject(base.Name).Visibility = False" diff --git a/src/Mod/Path/PathScripts/PathDressupPathBoundaryGui.py b/src/Mod/Path/Path/Dressup/Gui/Boundary.py similarity index 92% rename from src/Mod/Path/PathScripts/PathDressupPathBoundaryGui.py rename to src/Mod/Path/Path/Dressup/Gui/Boundary.py index 9339ba8159..0947f271b9 100644 --- a/src/Mod/Path/PathScripts/PathDressupPathBoundaryGui.py +++ b/src/Mod/Path/Path/Dressup/Gui/Boundary.py @@ -24,15 +24,15 @@ from PySide import QtGui from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathDressupPathBoundary as PathDressupPathBoundary -import PathScripts.PathLog as PathLog +import Path +import Path.Dressup.Boundary as PathDressupPathBoundary +import PathGui if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -112,11 +112,11 @@ class TaskPanel(object): self.setClean() def updateStockEditor(self, index, force=False): - import PathScripts.PathJobGui as PathJobGui - import PathScripts.PathStock as PathStock + import Path.Main.Gui.Job as PathJobGui + import Path.Main.Stock as PathStock def setupFromBaseEdit(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockFromBase: self.stockFromBase = PathJobGui.StockFromBaseBoundBoxEdit( self.obj, self.form, force @@ -124,7 +124,7 @@ class TaskPanel(object): self.stockEdit = self.stockFromBase def setupCreateBoxEdit(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockCreateBox: self.stockCreateBox = PathJobGui.StockCreateBoxEdit( self.obj, self.form, force @@ -132,7 +132,7 @@ class TaskPanel(object): self.stockEdit = self.stockCreateBox def setupCreateCylinderEdit(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockCreateCylinder: self.stockCreateCylinder = PathJobGui.StockCreateCylinderEdit( self.obj, self.form, force @@ -140,7 +140,7 @@ class TaskPanel(object): self.stockEdit = self.stockCreateCylinder def setupFromExisting(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockFromExisting: self.stockFromExisting = PathJobGui.StockFromExistingEdit( self.obj, self.form, force @@ -162,7 +162,7 @@ class TaskPanel(object): elif PathJobGui.StockFromExistingEdit.IsStock(self.obj): setupFromExisting() else: - PathLog.error( + Path.Log.error( translate("PathJob", "Unsupported stock object %s") % self.obj.Stock.Label ) @@ -178,7 +178,7 @@ class TaskPanel(object): setupFromBaseEdit() index = -1 else: - PathLog.error( + Path.Log.error( translate("PathJob", "Unsupported stock type %s (%d)") % (self.form.stock.currentText(), index) ) @@ -280,7 +280,7 @@ class CommandPathDressupPathBoundary: # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: - PathLog.error( + Path.Log.error( translate("Path_DressupPathBoundary", "Please select one path object") + "\n" ) @@ -289,9 +289,9 @@ class CommandPathDressupPathBoundary: # everything ok! FreeCAD.ActiveDocument.openTransaction("Create Path Boundary Dress-up") - FreeCADGui.addModule("PathScripts.PathDressupPathBoundaryGui") + FreeCADGui.addModule("Path.Dressup.Gui.Boundary") FreeCADGui.doCommand( - "PathScripts.PathDressupPathBoundaryGui.Create(App.ActiveDocument.%s)" + "Path.Dressup.Gui.Boundary.Create(App.ActiveDocument.%s)" % baseObject.Name ) # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() @@ -302,4 +302,4 @@ if FreeCAD.GuiUp: # register the FreeCAD command FreeCADGui.addCommand("Path_DressupPathBoundary", CommandPathDressupPathBoundary()) -PathLog.notice("Loading PathDressupPathBoundaryGui... done\n") +Path.Log.notice("Loading PathDressupPathBoundaryGui... done\n") diff --git a/src/Mod/Path/PathScripts/PathDressupDogbone.py b/src/Mod/Path/Path/Dressup/Gui/Dogbone.py similarity index 90% rename from src/Mod/Path/PathScripts/PathDressupDogbone.py rename to src/Mod/Path/Path/Dressup/Gui/Dogbone.py index 875e94a02a..1ffd6436fd 100644 --- a/src/Mod/Path/PathScripts/PathDressupDogbone.py +++ b/src/Mod/Path/Path/Dressup/Gui/Dogbone.py @@ -26,13 +26,10 @@ from PySide import QtCore from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Path -import PathScripts.PathDressup as PathDressup -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathUtil as PathUtil +import Path.Base.Util as PathUtil +import Path.Dressup.Utils as PathDressup import PathScripts.PathUtils as PathUtils import math -from PathScripts.PathGeom import CmdMoveCW, CmdMoveStraight, CmdMoveArc, CmdMoveRapid # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -42,20 +39,20 @@ Part = LazyLoader("Part", globals(), "Part") if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate -movecommands = CmdMoveStraight + CmdMoveRapid + CmdMoveArc +movecommands = Path.Geom.CmdMoveStraight + Path.Geom.CmdMoveRapid + Path.Geom.CmdMoveArc def debugMarker(vector, label, color=None, radius=0.5): - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label) obj.Label = label obj.Radius = radius @@ -67,7 +64,7 @@ def debugMarker(vector, label, color=None, radius=0.5): def debugCircle(vector, r, label, color=None): - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cylinder", label) obj.Label = label obj.Radius = r @@ -119,9 +116,9 @@ def edgesForCommands(cmds, startPt): for cmd in cmds: if cmd.Name in movecommands: pt = pointFromCommand(cmd, lastPt) - if cmd.Name in CmdMoveStraight: + if cmd.Name in Path.Geom.CmdMoveStraight: edges.append(Part.Edge(Part.LineSegment(lastPt, pt))) - elif cmd.Name in CmdMoveArc: + elif cmd.Name in Path.Geom.CmdMoveArc: center = lastPt + pointFromCommand( cmd, FreeCAD.Vector(0, 0, 0), "I", "J", "K" ) @@ -132,7 +129,7 @@ def edgesForCommands(cmds, startPt): if d == 0: # we're dealing with half a circle here angle = getAngle(A) + math.pi / 2 - if cmd.Name in CmdMoveCW: + if cmd.Name in Path.Geom.CmdMoveCW: angle -= math.pi else: C = A + B @@ -250,8 +247,8 @@ class Chord(object): def getDirectionOfVector(self, B): A = self.asDirection() # if the 2 vectors are identical, they head in the same direction - PathLog.debug(" {}.getDirectionOfVector({})".format(A, B)) - if PathGeom.pointsCoincide(A, B): + Path.Log.debug(" {}.getDirectionOfVector({})".format(A, B)) + if Path.Geom.pointsCoincide(A, B): return "Straight" d = -A.x * B.y + A.y * B.x if d < 0: @@ -307,23 +304,23 @@ class Chord(object): return self.arcCommand("G3", center, f) def isAPlungeMove(self): - return not PathGeom.isRoughly(self.End.z, self.Start.z) + return not Path.Geom.isRoughly(self.End.z, self.Start.z) def isANoopMove(self): - PathLog.debug( + Path.Log.debug( "{}.isANoopMove(): {}".format( - self, PathGeom.pointsCoincide(self.Start, self.End) + self, Path.Geom.pointsCoincide(self.Start, self.End) ) ) - return PathGeom.pointsCoincide(self.Start, self.End) + return Path.Geom.pointsCoincide(self.Start, self.End) def foldsBackOrTurns(self, chord, side): direction = chord.getDirectionOf(self) - PathLog.info(" - direction = %s/%s" % (direction, side)) + Path.Log.info(" - direction = %s/%s" % (direction, side)) return direction == "Back" or direction == side def connectsTo(self, chord): - return PathGeom.pointsCoincide(self.End, chord.Start) + return Path.Geom.pointsCoincide(self.End, chord.Start) class Bone(object): @@ -378,9 +375,9 @@ class Bone(object): # for some reason pi/2 is not equal to pi/2 if math.fabs(theta - boneAngle) < 0.00001: # moving directly towards the corner - PathLog.debug("adaptive - on target: %.2f - %.2f" % (distance, toolRadius)) + Path.Log.debug("adaptive - on target: %.2f - %.2f" % (distance, toolRadius)) return distance - toolRadius - PathLog.debug( + Path.Log.debug( "adaptive - angles: corner=%.2f bone=%.2f diff=%.12f" % (theta / math.pi, boneAngle / math.pi, theta - boneAngle) ) @@ -394,11 +391,11 @@ class Bone(object): beta = math.fabs(addAngle(boneAngle, -theta)) D = (distance / toolRadius) * math.sin(beta) if D > 1: # no intersection - PathLog.debug("adaptive - no intersection - no bone") + Path.Log.debug("adaptive - no intersection - no bone") return 0 gamma = math.asin(D) alpha = math.pi - beta - gamma - if PathGeom.isRoughly(0.0, math.sin(beta)): + if Path.Geom.isRoughly(0.0, math.sin(beta)): # it is not a good idea to divide by 0 length = 0.0 else: @@ -410,7 +407,7 @@ class Bone(object): length2 = toolRadius * math.sin(alpha2) / math.sin(beta2) length = min(length, length2) - PathLog.debug( + Path.Log.debug( "adaptive corner=%.2f * %.2f˚ -> bone=%.2f * %.2f˚" % (distance, theta, length, boneAngle) ) @@ -496,7 +493,7 @@ class ObjectDressup(object): # Answer true if a dogbone could be on either end of the chord, given its command def canAttachDogbone(self, cmd, chord): return ( - cmd.Name in CmdMoveStraight + cmd.Name in Path.Geom.CmdMoveStraight and not chord.isAPlungeMove() and not chord.isANoopMove() ) @@ -505,7 +502,7 @@ class ObjectDressup(object): return outChord.foldsBackOrTurns(inChord, self.theOtherSideOf(obj.Side)) def findPivotIntersection(self, pivot, pivotEdge, edge, refPt, d, color): - PathLog.track( + Path.Log.track( "(%.2f, %.2f)^%.2f - [(%.2f, %.2f), (%.2f, %.2f)]" % ( pivotEdge.Curve.Center.x, @@ -522,22 +519,22 @@ class ObjectDressup(object): for pt in DraftGeomUtils.findIntersection(edge, pivotEdge, dts=False): # debugMarker(pt, "pti.%d-%s.in" % (self.boneId, d), color, 0.2) distance = (pt - refPt).Length - PathLog.debug(" --> (%.2f, %.2f): %.2f" % (pt.x, pt.y, distance)) + Path.Log.debug(" --> (%.2f, %.2f): %.2f" % (pt.x, pt.y, distance)) if not ppt or pptDistance < distance: ppt = pt pptDistance = distance if not ppt: tangent = DraftGeomUtils.findDistance(pivot, edge) if tangent: - PathLog.debug("Taking tangent as intersect %s" % tangent) + Path.Log.debug("Taking tangent as intersect %s" % tangent) ppt = pivot + tangent else: - PathLog.debug( + Path.Log.debug( "Taking chord start as intersect %s" % edge.Vertexes[0].Point ) ppt = edge.Vertexes[0].Point # debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2) - PathLog.debug(" --> (%.2f, %.2f)" % (ppt.x, ppt.y)) + Path.Log.debug(" --> (%.2f, %.2f)" % (ppt.x, ppt.y)) return ppt def pointIsOnEdge(self, point, edge): @@ -548,7 +545,7 @@ class ObjectDressup(object): self, bone, inChord, outChord, edge, wire, corner, smooth, color=None ): if smooth == 0: - PathLog.info(" No smoothing requested") + Path.Log.info(" No smoothing requested") return [bone.lastCommand, outChord.g1Command(bone.F)] d = "in" @@ -558,13 +555,13 @@ class ObjectDressup(object): refPoint = outChord.End if DraftGeomUtils.areColinear(inChord.asEdge(), outChord.asEdge()): - PathLog.info(" straight edge %s" % d) + Path.Log.info(" straight edge %s" % d) return [outChord.g1Command(bone.F)] pivot = None pivotDistance = 0 - PathLog.info( + Path.Log.info( "smooth: (%.2f, %.2f)-(%.2f, %.2f)" % ( edge.Vertexes[0].Point.x, @@ -576,7 +573,7 @@ class ObjectDressup(object): for e in wire.Edges: self.dbg.append(e) if type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line: - PathLog.debug( + Path.Log.debug( " (%.2f, %.2f)-(%.2f, %.2f)" % ( e.Vertexes[0].Point.x, @@ -586,22 +583,22 @@ class ObjectDressup(object): ) ) else: - PathLog.debug( + Path.Log.debug( " (%.2f, %.2f)^%.2f" % (e.Curve.Center.x, e.Curve.Center.y, e.Curve.Radius) ) for pt in DraftGeomUtils.findIntersection(edge, e, True, findAll=True): - if not PathGeom.pointsCoincide(pt, corner) and self.pointIsOnEdge( + if not Path.Geom.pointsCoincide(pt, corner) and self.pointIsOnEdge( pt, e ): # debugMarker(pt, "candidate-%d-%s" % (self.boneId, d), color, 0.05) - PathLog.debug(" -> candidate") + Path.Log.debug(" -> candidate") distance = (pt - refPoint).Length if not pivot or pivotDistance > distance: pivot = pt pivotDistance = distance else: - PathLog.debug(" -> corner intersect") + Path.Log.debug(" -> corner intersect") if pivot: # debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color) @@ -617,20 +614,20 @@ class ObjectDressup(object): ) commands = [] - if not PathGeom.pointsCoincide(t1, inChord.Start): - PathLog.debug(" add lead in") + if not Path.Geom.pointsCoincide(t1, inChord.Start): + Path.Log.debug(" add lead in") commands.append(Chord(inChord.Start, t1).g1Command(bone.F)) if bone.obj.Side == Side.Left: - PathLog.debug(" add g3 command") + Path.Log.debug(" add g3 command") commands.append(Chord(t1, t2).g3Command(pivot, bone.F)) else: - PathLog.debug( + Path.Log.debug( " add g2 command center=(%.2f, %.2f) -> from (%2f, %.2f) to (%.2f, %.2f" % (pivot.x, pivot.y, t1.x, t1.y, t2.x, t2.y) ) commands.append(Chord(t1, t2).g2Command(pivot, bone.F)) - if not PathGeom.pointsCoincide(t2, outChord.End): - PathLog.debug(" add lead out") + if not Path.Geom.pointsCoincide(t2, outChord.End): + Path.Log.debug(" add lead out") commands.append(Chord(t2, outChord.End).g1Command(bone.F)) # debugMarker(pivot, "pivot.%d-%s" % (self.boneId, d), color, 0.2) @@ -639,7 +636,7 @@ class ObjectDressup(object): return commands - PathLog.info(" no pivot found - straight command") + Path.Log.info(" no pivot found - straight command") return [inChord.g1Command(bone.F), outChord.g1Command(bone.F)] def inOutBoneCommands(self, bone, boneAngle, fixedLength): @@ -647,7 +644,7 @@ class ObjectDressup(object): bone.tip = bone.inChord.End # in case there is no bone - PathLog.debug("corner = (%.2f, %.2f)" % (corner.x, corner.y)) + Path.Log.debug("corner = (%.2f, %.2f)" % (corner.x, corner.y)) # debugMarker(corner, 'corner', (1., 0., 1.), self.toolRadius) length = fixedLength @@ -657,7 +654,7 @@ class ObjectDressup(object): length = bone.adaptiveLength(boneAngle, self.toolRadius) if length == 0: - PathLog.info("no bone after all ..") + Path.Log.info("no bone after all ..") return [bone.lastCommand, bone.outChord.g1Command(bone.F)] # track length for marker visuals @@ -746,7 +743,7 @@ class ObjectDressup(object): def tboneVertical(self, bone): angle = bone.angle() boneAngle = math.pi / 2 - if PathGeom.isRoughly(angle, math.pi) or angle < 0: + if Path.Geom.isRoughly(angle, math.pi) or angle < 0: boneAngle = -boneAngle return self.inOutBoneCommands(bone, boneAngle, self.toolRadius) @@ -764,7 +761,7 @@ class ObjectDressup(object): onInString = "out" if onIn: onInString = "in" - PathLog.debug( + Path.Log.debug( "tboneEdge boneAngle[%s]=%.2f (in=%.2f, out=%.2f)" % ( onInString, @@ -815,7 +812,7 @@ class ObjectDressup(object): return [bone.lastCommand, bone.outChord.g1Command(bone.F)] def insertBone(self, bone): - PathLog.debug( + Path.Log.debug( ">----------------------------------- %d --------------------------------------" % bone.boneId ) @@ -826,7 +823,7 @@ class ObjectDressup(object): self.boneId = bone.boneId # Specific debugging `if` statement - # if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG and bone.boneId > 2: + # if Path.Log.getLevel(LOG_MODULE) == Path.Log.Level.DEBUG and bone.boneId > 2: # commands = self.boneCommands(bone, False) # else: # commands = self.boneCommands(bone, enabled) @@ -834,7 +831,7 @@ class ObjectDressup(object): bone.commands = commands self.shapes[bone.boneId] = self.boneShapes - PathLog.debug( + Path.Log.debug( "<----------------------------------- %d --------------------------------------" % bone.boneId ) @@ -854,9 +851,9 @@ class ObjectDressup(object): for pt in cutoff: # debugCircle(e1.Curve.Center, e1.Curve.Radius, "bone.%d-1" % (self.boneId), (1.,0.,0.)) # debugCircle(e2.Curve.Center, e2.Curve.Radius, "bone.%d-2" % (self.boneId), (0.,1.,0.)) - if PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide( pt, e1.valueAt(e1.LastParameter) - ) or PathGeom.pointsCoincide(pt, e2.valueAt(e2.FirstParameter)): + ) or Path.Geom.pointsCoincide(pt, e2.valueAt(e2.FirstParameter)): continue # debugMarker(pt, "it", (0.0, 1.0, 1.0)) # 1. remove all redundant commands @@ -869,7 +866,7 @@ class ObjectDressup(object): commands.append(c1) # 3. change where c2 starts, this depends on the command itself c2 = bone2.inCommands[j] - if c2.Name in CmdMoveArc: + if c2.Name in Path.Geom.CmdMoveArc: center = e2.Curve.Center offset = center - pt c2Params = c2.Parameters @@ -919,7 +916,7 @@ class ObjectDressup(object): # lastCommand = None # commands.append(thisCommand) # continue - PathLog.info("%3d: %s" % (i, thisCommand)) + Path.Log.info("%3d: %s" % (i, thisCommand)) if thisCommand.Name in movecommands: thisChord = lastChord.moveToParameters(thisCommand.Parameters) thisIsACandidate = self.canAttachDogbone(thisCommand, thisChord) @@ -929,7 +926,7 @@ class ObjectDressup(object): and lastCommand and self.shouldInsertDogbone(obj, lastChord, thisChord) ): - PathLog.info(" Found bone corner: {}".format(lastChord.End)) + Path.Log.info(" Found bone corner: {}".format(lastChord.End)) bone = Bone( boneId, obj, @@ -942,7 +939,7 @@ class ObjectDressup(object): bones = self.insertBone(bone) boneId += 1 if lastBone: - PathLog.info(" removing potential path crossing") + Path.Log.info(" removing potential path crossing") # debugMarker(thisChord.Start, "it", (1.0, 0.0, 1.0)) commands, bones = self.removePathCrossing( commands, lastBone, bone @@ -951,14 +948,14 @@ class ObjectDressup(object): lastCommand = bones[-1] lastBone = bone elif lastCommand and thisChord.isAPlungeMove(): - PathLog.info(" Looking for connection in odds and ends") + Path.Log.info(" Looking for connection in odds and ends") haveNewLastCommand = False for chord in ( chord for chord in oddsAndEnds if lastChord.connectsTo(chord) ): if self.shouldInsertDogbone(obj, lastChord, chord): - PathLog.info(" and there is one") - PathLog.debug( + Path.Log.info(" and there is one") + Path.Log.debug( " odd/end={} last={}".format(chord, lastChord) ) bone = Bone( @@ -973,7 +970,7 @@ class ObjectDressup(object): bones = self.insertBone(bone) boneId += 1 if lastBone: - PathLog.info(" removing potential path crossing") + Path.Log.info(" removing potential path crossing") # debugMarker(chord.Start, "it", (0.0, 1.0, 1.0)) commands, bones = self.removePathCrossing( commands, lastBone, bone @@ -987,16 +984,16 @@ class ObjectDressup(object): commands.append(thisCommand) lastBone = None elif thisIsACandidate: - PathLog.info(" is a candidate, keeping for later") + Path.Log.info(" is a candidate, keeping for later") if lastCommand: commands.append(lastCommand) lastCommand = thisCommand lastBone = None elif thisChord.isANoopMove(): - PathLog.info(" ignoring and dropping noop move") + Path.Log.info(" ignoring and dropping noop move") continue else: - PathLog.info(" nope") + Path.Log.info(" nope") if lastCommand: commands.append(lastCommand) lastCommand = None @@ -1004,43 +1001,43 @@ class ObjectDressup(object): lastBone = None if lastChord.isAPlungeMove() and thisIsACandidate: - PathLog.info(" adding to odds and ends") + Path.Log.info(" adding to odds and ends") oddsAndEnds.append(thisChord) lastChord = thisChord else: if thisCommand.Name[0] != "(": - PathLog.info(" Clean slate") + Path.Log.info(" Clean slate") if lastCommand: commands.append(lastCommand) lastCommand = None lastBone = None commands.append(thisCommand) # for cmd in commands: - # PathLog.debug("cmd = '%s'" % cmd) + # Path.Log.debug("cmd = '%s'" % cmd) path = Path.Path(commands) obj.Path = path def setup(self, obj, initial): - PathLog.info("Here we go ... ") + Path.Log.info("Here we go ... ") if initial: if hasattr(obj.Base, "BoneBlacklist"): # dressing up a bone dressup obj.Side = obj.Base.Side else: - PathLog.info("Default side = right") + Path.Log.info("Default side = right") # otherwise dogbones are opposite of the base path's side side = Side.Right if hasattr(obj.Base, "Side") and obj.Base.Side == "Inside": - PathLog.info("inside -> side = left") + Path.Log.info("inside -> side = left") side = Side.Left else: - PathLog.info("not inside -> side stays right") + Path.Log.info("not inside -> side stays right") if hasattr(obj.Base, "Direction") and obj.Base.Direction == "CCW": - PathLog.info("CCW -> switch sides") + Path.Log.info("CCW -> switch sides") side = Side.oppositeOf(side) else: - PathLog.info("CW -> stay on side") + Path.Log.info("CW -> stay on side") obj.Side = side self.toolRadius = 5 @@ -1074,7 +1071,7 @@ class ObjectDressup(object): class Marker(object): def __init__(self, pt, r, h): - if PathGeom.isRoughly(h, 0): + if Path.Geom.isRoughly(h, 0): h = 0.1 self.pt = pt self.r = r @@ -1214,18 +1211,18 @@ class TaskPanel(object): self.form.customLabel.setEnabled(customSelected) self.updateBoneList() - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: for obj in FreeCAD.ActiveDocument.Objects: if obj.Name.startswith("Shape"): FreeCAD.ActiveDocument.removeObject(obj.Name) - PathLog.info("object name %s" % self.obj.Name) + Path.Log.info("object name %s" % self.obj.Name) if hasattr(self.obj.Proxy, "shapes"): - PathLog.info("showing shapes attribute") + Path.Log.info("showing shapes attribute") for shapes in self.obj.Proxy.shapes.values(): for shape in shapes: Part.show(shape) else: - PathLog.info("no shapes attribute found") + Path.Log.info("no shapes attribute found") def updateModel(self): self.getFields() @@ -1275,12 +1272,12 @@ class TaskPanel(object): class SelObserver(object): def __init__(self): - import PathScripts.PathSelection as PST + import Path.Op.Gui.Selection as PST PST.eselect() def __del__(self): - import PathScripts.PathSelection as PST + import Path.Op.Gui.Selection as PST PST.clear() @@ -1343,7 +1340,7 @@ class ViewProviderDressup(object): def Create(base, name="DogboneDressup"): """ - Create(obj, name='DogboneDressup') ... dresses the given PathProfile/PathContour object with dogbones. + Create(obj, name='DogboneDressup') ... dresses the given Path.Op.Profile/PathContour object with dogbones. """ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) dbo = ObjectDressup(obj, base) @@ -1395,9 +1392,9 @@ class CommandDressupDogbone(object): # everything ok! FreeCAD.ActiveDocument.openTransaction("Create Dogbone Dress-up") - FreeCADGui.addModule("PathScripts.PathDressupDogbone") + FreeCADGui.addModule("Path.Dressup.Gui.Dogbone") FreeCADGui.doCommand( - "PathScripts.PathDressupDogbone.Create(FreeCAD.ActiveDocument.%s)" + "Path.Dressup.Gui.Dogbone.Create(FreeCAD.ActiveDocument.%s)" % baseObject.Name ) # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() diff --git a/src/Mod/Path/PathScripts/PathDressupDragknife.py b/src/Mod/Path/Path/Dressup/Gui/Dragknife.py similarity index 98% rename from src/Mod/Path/PathScripts/PathDressupDragknife.py rename to src/Mod/Path/Path/Dressup/Gui/Dragknife.py index 1f10cfc94d..d1f6699cd5 100644 --- a/src/Mod/Path/PathScripts/PathDressupDragknife.py +++ b/src/Mod/Path/Path/Dressup/Gui/Dragknife.py @@ -23,10 +23,10 @@ from __future__ import print_function import FreeCAD import Path +import Path.Base.Gui.Util as PathGuiUtil from PySide import QtCore import math import PathScripts.PathUtils as PathUtils -import PathScripts.PathGui as PathGui from PySide.QtCore import QT_TRANSLATE_NOOP # lazily loaded modules @@ -498,13 +498,13 @@ class TaskPanel: def __init__(self, obj): self.obj = obj self.form = FreeCADGui.PySideUic.loadUi(":/panels/DragKnifeEdit.ui") - self.filterAngle = PathGui.QuantitySpinBox( + self.filterAngle = PathGuiUtil.QuantitySpinBox( self.form.filterAngle, obj, "filterAngle" ) - self.offsetDistance = PathGui.QuantitySpinBox( + self.offsetDistance = PathGuiUtil.QuantitySpinBox( self.form.offsetDistance, obj, "offset" ) - self.pivotHeight = PathGui.QuantitySpinBox( + self.pivotHeight = PathGuiUtil.QuantitySpinBox( self.form.pivotHeight, obj, "pivotheight" ) @@ -639,18 +639,18 @@ class CommandDressupDragknife: # everything ok! FreeCAD.ActiveDocument.openTransaction("Create Dress-up") - FreeCADGui.addModule("PathScripts.PathDressupDragknife") + FreeCADGui.addModule("Path.Dressup.Gui.Dragknife") FreeCADGui.addModule("PathScripts.PathUtils") FreeCADGui.doCommand( 'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","DragknifeDressup")' ) - FreeCADGui.doCommand("PathScripts.PathDressupDragknife.ObjectDressup(obj)") + FreeCADGui.doCommand("Path.Dressup.Gui.Dragknife.ObjectDressup(obj)") FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name) FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)") FreeCADGui.doCommand("obj.Base = base") FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)") FreeCADGui.doCommand( - "obj.ViewObject.Proxy = PathScripts.PathDressupDragknife.ViewProviderDressup(obj.ViewObject)" + "obj.ViewObject.Proxy = Path.Dressup.Gui.Dragknife.ViewProviderDressup(obj.ViewObject)" ) FreeCADGui.doCommand( "Gui.ActiveDocument.getObject(base.Name).Visibility = False" diff --git a/src/Mod/Path/PathScripts/PathDressupLeadInOut.py b/src/Mod/Path/Path/Dressup/Gui/LeadInOut.py similarity index 95% rename from src/Mod/Path/PathScripts/PathDressupLeadInOut.py rename to src/Mod/Path/Path/Dressup/Gui/LeadInOut.py index e4e70395cb..bdb4f2b16b 100644 --- a/src/Mod/Path/PathScripts/PathDressupLeadInOut.py +++ b/src/Mod/Path/Path/Dressup/Gui/LeadInOut.py @@ -26,9 +26,7 @@ from __future__ import print_function import FreeCAD import FreeCADGui import Path -import PathScripts.PathDressup as PathDressup -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog +import Path.Dressup.Utils as PathDressup import PathScripts.PathUtils as PathUtils import math import copy @@ -42,10 +40,10 @@ from PathPythonGui.simple_edit_panel import SimpleEditPanel translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) movecommands = ["G1", "G01", "G2", "G02", "G3", "G03"] @@ -186,12 +184,12 @@ class ObjectDressup: if not obj.Base.Path: return if obj.Length < 0: - PathLog.error( + Path.Log.error( translate("Path_DressupLeadInOut", "Length/Radius positive not Null") + "\n" ) obj.Length = 0.1 - self.wire, self.rapids = PathGeom.wireForPath(obj.Base.Path) + self.wire, self.rapids = Path.Geom.wireForPath(obj.Base.Path) obj.Path = self.generateLeadInOutCurve(obj) def getDirectionOfPath(self, obj): @@ -268,12 +266,12 @@ class ObjectDressup: p0 = queue[0].Placement.Base p1 = queue[1].Placement.Base v = self.normalize(p1.sub(p0)) - PathLog.debug(" CURRENT_IN Line : P0 Z:{} p1 Z:{}".format(p0.z, p1.z)) + Path.Log.debug(" CURRENT_IN Line : P0 Z:{} p1 Z:{}".format(p0.z, p1.z)) else: p0 = queue[0].Placement.Base p1 = queue[1].Placement.Base v = self.normalize(p1.sub(p0)) - PathLog.debug( + Path.Log.debug( " CURRENT_IN ARC : P0 X:{} Y:{} P1 X:{} Y:{} ".format( p0.x, p0.y, p1.x, p1.y ) @@ -292,7 +290,7 @@ class ObjectDressup: vec_n = self.normalize(vec) vec_inv = self.invert(vec_n) vec_off = self.multiply(vec_inv, obj.ExtendLeadIn) - PathLog.debug( + Path.Log.debug( "LineCMD: {}, Vxinv: {}, Vyinv: {}, Vxoff: {}, Vyoff: {}".format( queue[0].Name, vec_inv.x, vec_inv.y, vec_off.x, vec_off.y ) @@ -423,7 +421,7 @@ class ObjectDressup: extendcommand = Path.Command("G1", {"X": p0.x, "Y": p0.y, "F": horizFeed}) results.append(extendcommand) else: - PathLog.debug(" CURRENT_IN Perp") + Path.Log.debug(" CURRENT_IN Perp") currLocation.update(results[-1].Parameters) currLocation["Z"] = p1.z @@ -464,7 +462,7 @@ class ObjectDressup: vec_n = self.normalize(vec) vec_inv = self.invert(vec_n) vec_off = self.multiply(vec_inv, obj.ExtendLeadOut) - PathLog.debug( + Path.Log.debug( "LineCMD: {}, Vxinv: {}, Vyinv: {}, Vxoff: {}, Vyoff: {}".format( queue[0].Name, vec_inv.x, vec_inv.y, vec_off.x, vec_off.y ) @@ -540,7 +538,7 @@ class ObjectDressup: ) results.append(extendcommand) else: - PathLog.debug(" CURRENT_IN Perp") + Path.Log.debug(" CURRENT_IN Perp") if obj.UseMachineCRC: # crc off results.append(Path.Command("G40", {})) @@ -560,7 +558,7 @@ class ObjectDressup: # Read in all commands for curCommand in obj.Base.Path.Commands: - PathLog.debug("CurCMD: {}".format(curCommand)) + Path.Log.debug("CurCMD: {}".format(curCommand)) if curCommand.Name not in movecommands + rapidcommands: # Don't worry about non-move commands, just add to output newpath.append(curCommand) @@ -587,7 +585,7 @@ class ObjectDressup: and prevCmd.Name in movecommands ): # Layer change within move cmds - PathLog.debug( + Path.Log.debug( "Layer change in move: {}->{}".format( currLocation["Z"], curCommand.z ) @@ -608,14 +606,14 @@ class ObjectDressup: # Go through each layer and add leadIn/Out idx = 0 for layer in layers: - PathLog.debug("Layer {}".format(idx)) + Path.Log.debug("Layer {}".format(idx)) if obj.LeadIn: temp = self.getLeadStart(obj, layer, action) newpath.extend(temp) for cmd in layer: - PathLog.debug("CurLoc: {}, NewCmd: {}!!".format(currLocation, cmd)) + Path.Log.debug("CurLoc: {}, NewCmd: {}!!".format(currLocation, cmd)) newpath.append(cmd) if obj.LeadOut: @@ -690,7 +688,7 @@ class ViewProviderDressup: def onDelete(self, arg1=None, arg2=None): """this makes sure that the base operation is added back to the project and visible""" - PathLog.debug("Deleting Dressup") + Path.Log.debug("Deleting Dressup") if arg1.Object and arg1.Object.Base: FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True job = PathUtils.findParentJob(self.obj) @@ -730,33 +728,33 @@ class CommandPathDressupLeadInOut: # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: - PathLog.error( + Path.Log.error( translate("Path_DressupLeadInOut", "Please select one path object") + "\n" ) return baseObject = selection[0] if not baseObject.isDerivedFrom("Path::Feature"): - PathLog.error( + Path.Log.error( translate("Path_DressupLeadInOut", "The selected object is not a path") + "\n" ) return if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): - PathLog.error( + Path.Log.error( translate("Path_DressupLeadInOut", "Please select a Profile object") ) return # everything ok! FreeCAD.ActiveDocument.openTransaction("Create LeadInOut Dressup") - FreeCADGui.addModule("PathScripts.PathDressupLeadInOut") + FreeCADGui.addModule("Path.Dressup.Gui.LeadInOut") FreeCADGui.addModule("PathScripts.PathUtils") FreeCADGui.doCommand( 'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "LeadInOutDressup")' ) FreeCADGui.doCommand( - "dbo = PathScripts.PathDressupLeadInOut.ObjectDressup(obj)" + "dbo = Path.Dressup.Gui.LeadInOut.ObjectDressup(obj)" ) FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name) FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)") @@ -764,7 +762,7 @@ class CommandPathDressupLeadInOut: FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)") FreeCADGui.doCommand("dbo.setup(obj)") FreeCADGui.doCommand( - "obj.ViewObject.Proxy = PathScripts.PathDressupLeadInOut.ViewProviderDressup(obj.ViewObject)" + "obj.ViewObject.Proxy = Path.Dressup.Gui.LeadInOut.ViewProviderDressup(obj.ViewObject)" ) FreeCADGui.doCommand( "Gui.ActiveDocument.getObject(base.Name).Visibility = False" @@ -777,4 +775,4 @@ if FreeCAD.GuiUp: # register the FreeCAD command FreeCADGui.addCommand("Path_DressupLeadInOut", CommandPathDressupLeadInOut()) -PathLog.notice("Loading Path_DressupLeadInOut... done\n") +Path.Log.notice("Loading Path_DressupLeadInOut... done\n") diff --git a/src/Mod/Path/PathScripts/PathPreferencesPathDressup.py b/src/Mod/Path/Path/Dressup/Gui/Preferences.py similarity index 100% rename from src/Mod/Path/PathScripts/PathPreferencesPathDressup.py rename to src/Mod/Path/Path/Dressup/Gui/Preferences.py diff --git a/src/Mod/Path/PathScripts/PathDressupRampEntry.py b/src/Mod/Path/Path/Dressup/Gui/RampEntry.py similarity index 92% rename from src/Mod/Path/PathScripts/PathDressupRampEntry.py rename to src/Mod/Path/Path/Dressup/Gui/RampEntry.py index 603b977a02..5b740bef3f 100644 --- a/src/Mod/Path/PathScripts/PathDressupRampEntry.py +++ b/src/Mod/Path/Path/Dressup/Gui/RampEntry.py @@ -24,9 +24,7 @@ from PathScripts import PathUtils from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Path -import PathScripts.PathDressup as PathDressup -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog +import Path.Dressup.Utils as PathDressup import math @@ -43,10 +41,10 @@ translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectDressup: @@ -158,11 +156,11 @@ class ObjectDressup: data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -224,7 +222,7 @@ class ObjectDressup: self.angle = obj.Angle self.method = obj.Method - self.wire, self.rapids = PathGeom.wireForPath(obj.Base.Path) + self.wire, self.rapids = Path.Geom.wireForPath(obj.Base.Path) if self.method in ["RampMethod1", "RampMethod2", "RampMethod3"]: self.outedges = self.generateRamps() else: @@ -237,7 +235,7 @@ class ObjectDressup: for edge in edges: israpid = False for redge in self.rapids: - if PathGeom.edgesMatch(edge, redge): + if Path.Geom.edgesMatch(edge, redge): israpid = True if not israpid: bb = edge.BoundBox @@ -263,7 +261,7 @@ class ObjectDressup: projectionlen = plungelen * math.tan( math.radians(rampangle) ) # length of the forthcoming ramp projected to XY plane - PathLog.debug( + Path.Log.debug( "Found plunge move at X:{} Y:{} From Z:{} to Z{}, length of ramp: {}".format( p0.x, p0.y, p0.z, p1.z, projectionlen ) @@ -284,7 +282,7 @@ class ObjectDressup: if abs(cp0.z - cp1.z) > 1e-6: # this edge is not parallel to XY plane, not qualified for ramping. break - # PathLog.debug("Next edge length {}".format(candidate.Length)) + # Path.Log.debug("Next edge length {}".format(candidate.Length)) rampedges.append(candidate) coveredlen = coveredlen + candidate.Length @@ -294,7 +292,7 @@ class ObjectDressup: if i >= len(edges): break if len(rampedges) == 0: - PathLog.debug( + Path.Log.debug( "No suitable edges for ramping, plunge will remain as such" ) outedges.append(edge) @@ -310,13 +308,13 @@ class ObjectDressup: ) else: rampangle = math.degrees(math.atan(l / plungelen)) - PathLog.warning( + Path.Log.warning( "Cannot cover with desired angle, tightening angle to: {}".format( rampangle ) ) - # PathLog.debug("Doing ramp to edges: {}".format(rampedges)) + # Path.Log.debug("Doing ramp to edges: {}".format(rampedges)) if self.method == "RampMethod1": outedges.extend( self.createRampMethod1( @@ -355,14 +353,14 @@ class ObjectDressup: def generateHelix(self): edges = self.wire.Edges minZ = self.findMinZ(edges) - PathLog.debug("Minimum Z in this path is {}".format(minZ)) + Path.Log.debug("Minimum Z in this path is {}".format(minZ)) outedges = [] i = 0 while i < len(edges): edge = edges[i] israpid = False for redge in self.rapids: - if PathGeom.edgesMatch(edge, redge): + if Path.Geom.edgesMatch(edge, redge): israpid = True if not israpid: bb = edge.BoundBox @@ -375,7 +373,7 @@ class ObjectDressup: and p0.z > p1.z ): # plungelen = abs(p0.z-p1.z) - PathLog.debug( + Path.Log.debug( "Found plunge move at X:{} Y:{} From Z:{} to Z{}, Searching for closed loop".format( p0.x, p0.y, p0.z, p1.z ) @@ -396,7 +394,7 @@ class ObjectDressup: candidate = edges[j] cp0 = candidate.Vertexes[0].Point cp1 = candidate.Vertexes[1].Point - if PathGeom.pointsCoincide(p1, cp1): + if Path.Geom.pointsCoincide(p1, cp1): # found closed loop loopFound = True rampedges.append(candidate) @@ -404,17 +402,17 @@ class ObjectDressup: if abs(cp0.z - cp1.z) > 1e-6: # this edge is not parallel to XY plane, not qualified for ramping. break - # PathLog.debug("Next edge length {}".format(candidate.Length)) + # Path.Log.debug("Next edge length {}".format(candidate.Length)) rampedges.append(candidate) j = j + 1 if j >= len(edges): break if len(rampedges) == 0 or not loopFound: - PathLog.debug("No suitable helix found") + Path.Log.debug("No suitable helix found") outedges.append(edge) else: outedges.extend(self.createHelix(rampedges, p0, p1)) - if not PathGeom.isRoughly(p1.z, minZ): + if not Path.Geom.isRoughly(p1.z, minZ): # the edges covered by the helix not handled again, # unless reached the bottom height i = j @@ -432,14 +430,14 @@ class ObjectDressup: p1 = edge.Vertexes[1].Point if p0.z > self.ignoreAbove and ( p1.z > self.ignoreAbove - or PathGeom.isRoughly(p1.z, self.ignoreAbove.Value) + or Path.Geom.isRoughly(p1.z, self.ignoreAbove.Value) ): - PathLog.debug("Whole plunge move above 'ignoreAbove', ignoring") + Path.Log.debug("Whole plunge move above 'ignoreAbove', ignoring") return (edge, True) - elif p0.z > self.ignoreAbove and not PathGeom.isRoughly( + elif p0.z > self.ignoreAbove and not Path.Geom.isRoughly( p0.z, self.ignoreAbove.Value ): - PathLog.debug( + Path.Log.debug( "Plunge move partially above 'ignoreAbove', splitting into two" ) newPoint = FreeCAD.Base.Vector(p0.x, p0.y, self.ignoreAbove) @@ -474,7 +472,7 @@ class ObjectDressup: return outedges def createRampEdge(self, originalEdge, startPoint, endPoint): - # PathLog.debug("Create edge from [{},{},{}] to [{},{},{}]".format(startPoint.x,startPoint.y, startPoint.z, endPoint.x, endPoint.y, endPoint.z)) + # Path.Log.debug("Create edge from [{},{},{}] to [{},{},{}]".format(startPoint.x,startPoint.y, startPoint.z, endPoint.x, endPoint.y, endPoint.z)) if ( type(originalEdge.Curve) == Part.Line or type(originalEdge.Curve) == Part.LineSegment @@ -487,7 +485,7 @@ class ObjectDressup: arcMid.z = (startPoint.z + endPoint.z) / 2 return Part.Arc(startPoint, arcMid, endPoint).toShape() else: - PathLog.error("Edge should not be helix") + Path.Log.error("Edge should not be helix") def getreversed(self, edges): """ @@ -504,7 +502,7 @@ class ObjectDressup: arcMid = edge.valueAt((edge.FirstParameter + edge.LastParameter) / 2) outedges.append(Part.Arc(startPoint, arcMid, endPoint).toShape()) else: - PathLog.error("Edge should not be helix") + Path.Log.error("Edge should not be helix") return outedges def findMinZ(self, edges): @@ -544,9 +542,9 @@ class ObjectDressup: if redge.Length >= rampremaining: # will reach end of ramp within this edge, needs to be split p1 = self.getSplitPoint(redge, rampremaining) - splitEdge = PathGeom.splitEdgeAt(redge, p1) - PathLog.debug("Ramp remaining: {}".format(rampremaining)) - PathLog.debug( + splitEdge = Path.Geom.splitEdgeAt(redge, p1) + Path.Log.debug("Ramp remaining: {}".format(rampremaining)) + Path.Log.debug( "Got split edge (index: {}) (total len: {}) with lengths: {}, {}".format( i, redge.Length, splitEdge[0].Length, splitEdge[1].Length ) @@ -585,7 +583,7 @@ class ObjectDressup: if not done: # we did not reach the end of the ramp going this direction, lets reverse. rampedges = self.getreversed(rampedges) - PathLog.debug("Reversing") + Path.Log.debug("Reversing") if goingForward: goingForward = False else: @@ -627,8 +625,8 @@ class ObjectDressup: if redge.Length >= rampremaining: # will reach end of ramp within this edge, needs to be split p1 = self.getSplitPoint(redge, rampremaining) - splitEdge = PathGeom.splitEdgeAt(redge, p1) - PathLog.debug( + splitEdge = Path.Geom.splitEdgeAt(redge, p1) + Path.Log.debug( "Got split edge (index: {}) with lengths: {}, {}".format( i, splitEdge[0].Length, splitEdge[1].Length ) @@ -703,11 +701,11 @@ class ObjectDressup: outedges = [] rampremaining = projectionlen curPoint = p0 # start from the upper point of plunge - if PathGeom.pointsCoincide( - PathGeom.xy(p0), - PathGeom.xy(rampedges[-1].valueAt(rampedges[-1].LastParameter)), + if Path.Geom.pointsCoincide( + Path.Geom.xy(p0), + Path.Geom.xy(rampedges[-1].valueAt(rampedges[-1].LastParameter)), ): - PathLog.debug( + Path.Log.debug( "The ramp forms a closed wire, needless to move on original Z height" ) else: @@ -715,8 +713,8 @@ class ObjectDressup: if redge.Length >= rampremaining: # this edge needs to be split p1 = self.getSplitPoint(redge, rampremaining) - splitEdge = PathGeom.splitEdgeAt(redge, p1) - PathLog.debug( + splitEdge = Path.Geom.splitEdgeAt(redge, p1) + Path.Log.debug( "Got split edges with lengths: {}, {}".format( splitEdge[0].Length, splitEdge[1].Length ) @@ -786,13 +784,13 @@ class ObjectDressup: for edge in edges: israpid = False for redge in self.rapids: - if PathGeom.edgesMatch(edge, redge): + if Path.Geom.edgesMatch(edge, redge): israpid = True if israpid: v = edge.valueAt(edge.LastParameter) commands.append(Path.Command("G0", {"X": v.x, "Y": v.y, "Z": v.z})) else: - commands.extend(PathGeom.cmdsForEdge(edge)) + commands.extend(Path.Geom.cmdsForEdge(edge)) lastCmd = Path.Command("G0", {"X": 0.0, "Y": 0.0, "Z": 0.0}) @@ -831,7 +829,7 @@ class ObjectDressup: if cmd.Name in ["G1", "G2", "G3", "G01", "G02", "G03"]: if zVal is not None and zVal2 != zVal: - if PathGeom.isRoughly(xVal, xVal2) and PathGeom.isRoughly( + if Path.Geom.isRoughly(xVal, xVal2) and Path.Geom.isRoughly( yVal, yVal2 ): # this is a straight plunge @@ -877,7 +875,7 @@ class ViewProviderDressup: def onDelete(self, arg1=None, arg2=None): """this makes sure that the base operation is added back to the project and visible""" - PathLog.debug("Deleting Dressup") + Path.Log.debug("Deleting Dressup") if arg1.Object and arg1.Object.Base: FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True job = PathUtils.findParentJob(self.obj) @@ -917,40 +915,40 @@ class CommandPathDressupRampEntry: # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: - PathLog.error( + Path.Log.error( translate("Path_DressupRampEntry", "Please select one path object") + "\n" ) return baseObject = selection[0] if not baseObject.isDerivedFrom("Path::Feature"): - PathLog.error( + Path.Log.error( translate("Path_DressupRampEntry", "The selected object is not a path") + "\n" ) return if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): - PathLog.error( + Path.Log.error( translate("Path_DressupRampEntry", "Please select a Profile object") ) return # everything ok! FreeCAD.ActiveDocument.openTransaction("Create RampEntry Dress-up") - FreeCADGui.addModule("PathScripts.PathDressupRampEntry") + FreeCADGui.addModule("Path.Dressup.Gui.RampEntry") FreeCADGui.addModule("PathScripts.PathUtils") FreeCADGui.doCommand( 'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "RampEntryDressup")' ) FreeCADGui.doCommand( - "dbo = PathScripts.PathDressupRampEntry.ObjectDressup(obj)" + "dbo = Path.Dressup.Gui.RampEntry.ObjectDressup(obj)" ) FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name) FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)") FreeCADGui.doCommand("obj.Base = base") FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)") FreeCADGui.doCommand( - "obj.ViewObject.Proxy = PathScripts.PathDressupRampEntry.ViewProviderDressup(obj.ViewObject)" + "obj.ViewObject.Proxy = Path.Dressup.Gui.RampEntry.ViewProviderDressup(obj.ViewObject)" ) FreeCADGui.doCommand( "Gui.ActiveDocument.getObject(base.Name).Visibility = False" @@ -964,4 +962,4 @@ if FreeCAD.GuiUp: # register the FreeCAD command FreeCADGui.addCommand("Path_DressupRampEntry", CommandPathDressupRampEntry()) -PathLog.notice("Loading Path_DressupRampEntry... done\n") +Path.Log.notice("Loading Path_DressupRampEntry... done\n") diff --git a/src/Mod/Path/PathScripts/PathDressupTagPreferences.py b/src/Mod/Path/Path/Dressup/Gui/TagPreferences.py similarity index 87% rename from src/Mod/Path/PathScripts/PathDressupTagPreferences.py rename to src/Mod/Path/Path/Dressup/Gui/TagPreferences.py index c242e6c564..ad48f46dc8 100644 --- a/src/Mod/Path/PathScripts/PathDressupTagPreferences.py +++ b/src/Mod/Path/Path/Dressup/Gui/TagPreferences.py @@ -21,15 +21,14 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathPreferencesPathDressup as PathPreferencesPathDressup +import Path +import Path.Dressup.Gui.Preferences as PathPreferencesPathDressup if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -43,7 +42,7 @@ class HoldingTagPreferences: @classmethod def defaultWidth(cls, ifNotSet): - value = PathPreferences.preferences().GetFloat( + value = Path.Preferences.preferences().GetFloat( cls.DefaultHoldingTagWidth, ifNotSet ) if value == 0.0: @@ -52,7 +51,7 @@ class HoldingTagPreferences: @classmethod def defaultHeight(cls, ifNotSet): - value = PathPreferences.preferences().GetFloat( + value = Path.Preferences.preferences().GetFloat( cls.DefaultHoldingTagHeight, ifNotSet ) if value == 0.0: @@ -61,7 +60,7 @@ class HoldingTagPreferences: @classmethod def defaultAngle(cls, ifNotSet=45.0): - value = PathPreferences.preferences().GetFloat( + value = Path.Preferences.preferences().GetFloat( cls.DefaultHoldingTagAngle, ifNotSet ) if value < 10.0: @@ -70,7 +69,7 @@ class HoldingTagPreferences: @classmethod def defaultCount(cls, ifNotSet=4): - value = PathPreferences.preferences().GetUnsigned( + value = Path.Preferences.preferences().GetUnsigned( cls.DefaultHoldingTagCount, ifNotSet ) if value < 2: @@ -79,7 +78,7 @@ class HoldingTagPreferences: @classmethod def defaultRadius(cls, ifNotSet=0.0): - return PathPreferences.preferences().GetFloat( + return Path.Preferences.preferences().GetFloat( cls.DefaultHoldingTagRadius, ifNotSet ) @@ -112,7 +111,7 @@ class HoldingTagPreferences: self.form.sbCount.setValue(self.defaultCount()) def saveSettings(self): - pref = PathPreferences.preferences() + pref = Path.Preferences.preferences() pref.SetFloat( self.DefaultHoldingTagWidth, FreeCAD.Units.Quantity(self.form.ifWidth.text()).Value, diff --git a/src/Mod/Path/PathScripts/PathDressupTagGui.py b/src/Mod/Path/Path/Dressup/Gui/Tags.py similarity index 93% rename from src/Mod/Path/PathScripts/PathDressupTagGui.py rename to src/Mod/Path/Path/Dressup/Gui/Tags.py index ff8e719bb2..0ec1c9d5ad 100644 --- a/src/Mod/Path/PathScripts/PathDressupTagGui.py +++ b/src/Mod/Path/Path/Dressup/Gui/Tags.py @@ -25,26 +25,24 @@ from PySide.QtCore import QT_TRANSLATE_NOOP from pivy import coin import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathDressupHoldingTags as PathDressupTag -import PathScripts.PathGeom as PathGeom -import PathScripts.PathGetPoint as PathGetPoint -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences +import Path +import Path.Base.Gui.GetPoint as PathGetPoint +import Path.Dressup.Tags as PathDressupTag +import PathGui import PathScripts.PathUtils as PathUtils if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate def addDebugDisplay(): - return PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG + return Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG class PathDressupTagTaskPanel: @@ -164,7 +162,7 @@ class PathDressupTagTaskPanel: self.isDirty = True def updateTagsView(self): - PathLog.track() + Path.Log.track() self.form.lwTags.blockSignals(True) self.form.lwTags.clear() for i, pos in enumerate(self.Positions): @@ -189,7 +187,7 @@ class PathDressupTagTaskPanel: def generateNewTags(self): count = self.form.sbCount.value() - PathLog.track(count) + Path.Log.track(count) if not self.obj.Proxy.generateTags(self.obj, count): self.obj.Proxy.execute(self.obj) self.Positions = self.obj.Positions @@ -206,7 +204,7 @@ class PathDressupTagTaskPanel: self.Disabled = self.obj.Disabled self.updateTagsView() else: - PathLog.error("Cannot copy tags - internal error") + Path.Log.error("Cannot copy tags - internal error") def updateModel(self): self.getFields() @@ -218,7 +216,7 @@ class PathDressupTagTaskPanel: self.form.pbGenerate.setEnabled(count) def selectTagWithId(self, index): - PathLog.track(index) + Path.Log.track(index) self.form.lwTags.setCurrentRow(index) def whenTagSelectionChanged(self): @@ -242,18 +240,18 @@ class PathDressupTagTaskPanel: def addNewTagAt(self, point, obj): if point and obj and self.obj.Proxy.pointIsOnPath(self.obj, point): - PathLog.info("addNewTagAt(%.2f, %.2f)" % (point.x, point.y)) + Path.Log.info("addNewTagAt(%.2f, %.2f)" % (point.x, point.y)) self.Positions.append(FreeCAD.Vector(point.x, point.y, 0)) self.updateTagsView() else: - PathLog.notice("ignore new tag at %s (obj=%s, on-path=%d" % (point, obj, 0)) + Path.Log.notice("ignore new tag at %s (obj=%s, on-path=%d" % (point, obj, 0)) def addNewTag(self): self.tags = self.getTags(True) self.getPoint.getPoint(self.addNewTagAt) def editTagAt(self, point, obj): - PathLog.track(point, obj) + Path.Log.track(point, obj) if point and self.obj.Proxy.pointIsOnPath(self.obj, point): tags = [] for i, (x, y, enabled) in enumerate(self.tags): @@ -363,7 +361,7 @@ class HoldingTagMarker: class PathDressupTagViewProvider: def __init__(self, vobj): - PathLog.track() + Path.Log.track() self.vobj = vobj self.panel = None @@ -395,7 +393,7 @@ class PathDressupTagViewProvider: v = [((val >> n) & 0xFF) / 255.0 for n in [24, 16, 8, 0]] return coin.SbColor(v[0], v[1], v[2]) - pref = PathPreferences.preferences() + pref = Path.Preferences.preferences() # R G B A npc = pref.GetUnsigned( "DefaultPathMarkerColor", ((85 * 256 + 255) * 256 + 0) * 256 + 255 @@ -413,7 +411,7 @@ class PathDressupTagViewProvider: ] def attach(self, vobj): - PathLog.track() + Path.Log.track() self.setupColors() self.vobj = vobj self.obj = vobj.Object @@ -438,14 +436,14 @@ class PathDressupTagViewProvider: self.switch.whichChild = sw def claimChildren(self): - PathLog.track() + Path.Log.track() # if self.debugDisplay(): # return [self.obj.Base, self.vobj.Debug] return [self.obj.Base] def onDelete(self, arg1=None, arg2=None): """this makes sure that the base operation is added back to the job and visible""" - PathLog.track() + Path.Log.track() if self.obj.Base and self.obj.Base.ViewObject: self.obj.Base.ViewObject.Visibility = True job = PathUtils.findParentJob(self.obj) @@ -472,12 +470,12 @@ class PathDressupTagViewProvider: self.tags = tags def updateData(self, obj, propName): - PathLog.track(propName) + Path.Log.track(propName) if "Disabled" == propName: self.updatePositions(obj.Positions, obj.Disabled) def onModelChanged(self): - PathLog.track() + Path.Log.track() # if self.debugDisplay(): # self.vobj.Debug.removeObjectsFromDocument() # for solid in self.obj.Proxy.solids: @@ -515,7 +513,7 @@ class PathDressupTagViewProvider: # SelectionObserver interface def selectTag(self, index): - PathLog.track(index) + Path.Log.track(index) for i, tag in enumerate(self.tags): tag.setSelected(i == index) @@ -527,7 +525,7 @@ class PathDressupTagViewProvider: z = self.tags[0].point.z p = FreeCAD.Vector(x, y, z) for i, tag in enumerate(self.tags): - if PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide( p, tag.point, tag.sphere.radius.getValue() * 1.3 ): return i @@ -539,7 +537,7 @@ class PathDressupTagViewProvider: return False def addSelection(self, doc, obj, sub, point): - PathLog.track(doc, obj, sub, point) + Path.Log.track(doc, obj, sub, point) if self.panel: i = self.tagAtPoint(point, sub is None) self.panel.selectTagWithId(i) @@ -580,7 +578,7 @@ class CommandPathDressupTag: # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: - PathLog.error( + Path.Log.error( translate("Path_DressupTag", "Please select one path object") + "\n" ) return @@ -588,9 +586,9 @@ class CommandPathDressupTag: # everything ok! FreeCAD.ActiveDocument.openTransaction("Create Tag Dress-up") - FreeCADGui.addModule("PathScripts.PathDressupTagGui") + FreeCADGui.addModule("Path.Dressup.Gui.Tags") FreeCADGui.doCommand( - "PathScripts.PathDressupTagGui.Create(App.ActiveDocument.%s)" + "Path.Dressup.Gui.Tags.Create(App.ActiveDocument.%s)" % baseObject.Name ) # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() @@ -601,4 +599,4 @@ if FreeCAD.GuiUp: # register the FreeCAD command FreeCADGui.addCommand("Path_DressupTag", CommandPathDressupTag()) -PathLog.notice("Loading PathDressupTagGui... done\n") +Path.Log.notice("Loading PathDressupTagGui... done\n") diff --git a/src/Mod/Path/PathScripts/PathDressupZCorrect.py b/src/Mod/Path/Path/Dressup/Gui/ZCorrect.py similarity index 92% rename from src/Mod/Path/PathScripts/PathDressupZCorrect.py rename to src/Mod/Path/Path/Dressup/Gui/ZCorrect.py index e9af62107a..15f884ecc7 100644 --- a/src/Mod/Path/PathScripts/PathDressupZCorrect.py +++ b/src/Mod/Path/Path/Dressup/Gui/ZCorrect.py @@ -26,13 +26,10 @@ import FreeCAD import FreeCADGui import Path -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog import PathScripts.PathUtils as PathUtils from PySide import QtGui from PySide.QtCore import QT_TRANSLATE_NOOP -from PathScripts.PathGeom import CmdMoveArc, CmdMoveStraight # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -44,13 +41,13 @@ Part = LazyLoader("Part", globals(), "Part") LOGLEVEL = False -LOG_MODULE = PathLog.thisModule() +LOG_MODULE = Path.Log.thisModule() if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -130,12 +127,12 @@ class ObjectDressup: zval = round(float(w[2]), 2) pointlist.append([xval, yval, zval]) - PathLog.debug(pointlist) + Path.Log.debug(pointlist) cols = list(zip(*pointlist)) - PathLog.debug("cols: {}".format(cols)) + Path.Log.debug("cols: {}".format(cols)) yindex = list(sorted(set(cols[1]))) - PathLog.debug("yindex: {}".format(yindex)) + Path.Log.debug("yindex: {}".format(yindex)) array = [] for y in yindex: @@ -173,20 +170,20 @@ class ObjectDressup: currLocation = {"X": 0, "Y": 0, "Z": 0, "F": 0} for c in pathlist: - PathLog.debug(c) - PathLog.debug(" curLoc:{}".format(currLocation)) + Path.Log.debug(c) + Path.Log.debug(" curLoc:{}".format(currLocation)) newparams = dict(c.Parameters) zval = newparams.get("Z", currLocation["Z"]) - if c.Name in CmdMoveStraight + CmdMoveArc: + if c.Name in Path.Geom.CmdMoveStraight + Path.Geom.CmdMoveArc: curVec = FreeCAD.Vector( currLocation["X"], currLocation["Y"], currLocation["Z"], ) - arcwire = PathGeom.edgeForCmd(c, curVec) + arcwire = Path.Geom.edgeForCmd(c, curVec) if arcwire is None: continue - if c.Name in CmdMoveArc: + if c.Name in Path.Geom.CmdMoveArc: pointlist = arcwire.discretize(Deflection=curveD) else: disc_number = int(arcwire.Length / sampleD) @@ -254,18 +251,18 @@ class TaskPanel: def updateUI(self): - if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: + if Path.Log.getLevel(LOG_MODULE) == Path.Log.Level.DEBUG: for obj in FreeCAD.ActiveDocument.Objects: if obj.Name.startswith("Shape"): FreeCAD.ActiveDocument.removeObject(obj.Name) print("object name %s" % self.obj.Name) if hasattr(self.obj.Proxy, "shapes"): - PathLog.info("showing shapes attribute") + Path.Log.info("showing shapes attribute") for shapes in self.obj.Proxy.shapes.itervalues(): for shape in shapes: Part.show(shape) else: - PathLog.info("no shapes attribute found") + Path.Log.info("no shapes attribute found") def updateModel(self): self.getFields() @@ -381,15 +378,15 @@ class CommandPathDressup: # everything ok! FreeCAD.ActiveDocument.openTransaction("Create Dress-up") - FreeCADGui.addModule("PathScripts.PathDressupZCorrect") + FreeCADGui.addModule("Path.Dressup.Gui.ZCorrect") FreeCADGui.addModule("PathScripts.PathUtils") FreeCADGui.doCommand( 'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "ZCorrectDressup")' ) - FreeCADGui.doCommand("PathScripts.PathDressupZCorrect.ObjectDressup(obj)") + FreeCADGui.doCommand("Path.Dressup.Gui.ZCorrect.ObjectDressup(obj)") FreeCADGui.doCommand("obj.Base = FreeCAD.ActiveDocument." + selection[0].Name) FreeCADGui.doCommand( - "PathScripts.PathDressupZCorrect.ViewProviderDressup(obj.ViewObject)" + "Path.Dressup.Gui.ZCorrect.ViewProviderDressup(obj.ViewObject)" ) FreeCADGui.doCommand("PathScripts.PathUtils.addToJob(obj)") FreeCADGui.doCommand( diff --git a/src/Mod/Path/Path/Dressup/Gui/__init__.py b/src/Mod/Path/Path/Dressup/Gui/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py b/src/Mod/Path/Path/Dressup/Tags.py similarity index 85% rename from src/Mod/Path/PathScripts/PathDressupHoldingTags.py rename to src/Mod/Path/Path/Dressup/Tags.py index 57a38c6285..bc4adec927 100644 --- a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py +++ b/src/Mod/Path/Path/Dressup/Tags.py @@ -20,15 +20,13 @@ # * * # *************************************************************************** -from PathScripts.PathDressupTagPreferences import HoldingTagPreferences +from Path.Dressup.Gui.TagPreferences import HoldingTagPreferences from PathScripts.PathUtils import waiting_effects from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Path -import PathScripts.PathDressup as PathDressup -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathUtil as PathUtil +import Path.Base.Util as PathUtil +import Path.Dressup.Utils as PathDressup import PathScripts.PathUtils as PathUtils import copy import math @@ -40,16 +38,16 @@ from lazy_loader.lazy_loader import LazyLoader Part = LazyLoader("Part", globals(), "Part") if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate def debugEdge(edge, prefix, force=False): - if force or PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if force or Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: pf = edge.valueAt(edge.FirstParameter) pl = edge.valueAt(edge.LastParameter) if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment: @@ -78,7 +76,7 @@ def debugEdge(edge, prefix, force=False): def debugMarker(vector, label, color=None, radius=0.5): - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label) obj.Label = label obj.Radius = radius @@ -90,7 +88,7 @@ def debugMarker(vector, label, color=None, radius=0.5): def debugCylinder(vector, r, height, label, color=None): - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cylinder", label) obj.Label = label obj.Radius = r @@ -104,7 +102,7 @@ def debugCylinder(vector, r, height, label, color=None): def debugCone(vector, r1, r2, height, label, color=None): - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cone", label) obj.Label = label obj.Radius1 = r1 @@ -120,7 +118,7 @@ def debugCone(vector, r1, r2, height, label, color=None): class Tag: def __init__(self, nr, x, y, width, height, angle, radius, enabled=True): - PathLog.track( + Path.Log.track( "%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d" % (x, y, width, height, angle, radius, enabled) ) @@ -165,12 +163,12 @@ class Tag: self.r2 = r1 height = self.height * 1.01 radius = 0 - if PathGeom.isRoughly(90, self.angle) and height > 0: + if Path.Geom.isRoughly(90, self.angle) and height > 0: # cylinder self.isSquare = True self.solid = Part.makeCylinder(r1, height) radius = min(min(self.radius, r1), self.height) - PathLog.debug("Part.makeCylinder(%f, %f)" % (r1, height)) + Path.Log.debug("Part.makeCylinder(%f, %f)" % (r1, height)) elif self.angle > 0.0 and height > 0.0: # cone rad = math.radians(self.angle) @@ -187,25 +185,25 @@ class Tag: height = r1 * tangens * 1.01 self.actualHeight = height self.r2 = r2 - PathLog.debug("Part.makeCone(%f, %f, %f)" % (r1, r2, height)) + Path.Log.debug("Part.makeCone(%f, %f, %f)" % (r1, r2, height)) self.solid = Part.makeCone(r1, r2, height) else: # degenerated case - no tag - PathLog.debug("Part.makeSphere(%f / 10000)" % (r1)) + Path.Log.debug("Part.makeSphere(%f / 10000)" % (r1)) self.solid = Part.makeSphere(r1 / 10000) - if not PathGeom.isRoughly( + if not Path.Geom.isRoughly( 0, R ): # testing is easier if the solid is not rotated - angle = -PathGeom.getAngle(self.originAt(0)) * 180 / math.pi - PathLog.debug("solid.rotate(%f)" % angle) + angle = -Path.Geom.getAngle(self.originAt(0)) * 180 / math.pi + Path.Log.debug("solid.rotate(%f)" % angle) self.solid.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), angle) orig = self.originAt(z - 0.01 * self.actualHeight) - PathLog.debug("solid.translate(%s)" % orig) + Path.Log.debug("solid.translate(%s)" % orig) self.solid.translate(orig) radius = min(self.radius, radius) self.realRadius = radius - if not PathGeom.isRoughly(0, radius): - PathLog.debug("makeFillet(%.4f)" % radius) + if not Path.Geom.isRoughly(0, radius): + Path.Log.debug("makeFillet(%.4f)" % radius) self.solid = self.solid.makeFillet(radius, [self.solid.Edges[0]]) def filterIntersections(self, pts, face): @@ -214,12 +212,12 @@ class Tag: or type(face.Surface) == Part.Cylinder or type(face.Surface) == Part.Toroid ): - PathLog.track("it's a cone/cylinder, checking z") + Path.Log.track("it's a cone/cylinder, checking z") return list( [pt for pt in pts if pt.z >= self.bottom() and pt.z <= self.top()] ) if type(face.Surface) == Part.Plane: - PathLog.track("it's a plane, checking R") + Path.Log.track("it's a plane, checking R") c = face.Edges[0].Curve if type(c) == Part.Circle: return list( @@ -227,10 +225,10 @@ class Tag: pt for pt in pts if (pt - c.Center).Length <= c.Radius - or PathGeom.isRoughly((pt - c.Center).Length, c.Radius) + or Path.Geom.isRoughly((pt - c.Center).Length, c.Radius) ] ) - PathLog.error("==== we got a %s" % face.Surface) + Path.Log.error("==== we got a %s" % face.Surface) def isPointOnEdge(self, pt, edge): param = edge.Curve.parameter(pt) @@ -238,7 +236,7 @@ class Tag: return True if edge.LastParameter <= param <= edge.FirstParameter: return True - if PathGeom.isRoughly(edge.FirstParameter, param) or PathGeom.isRoughly( + if Path.Geom.isRoughly(edge.FirstParameter, param) or Path.Geom.isRoughly( edge.LastParameter, param ): return True @@ -266,7 +264,7 @@ class Tag: def intersects(self, edge, param): def isDefinitelySmaller(z, zRef): # Eliminate false positives of edges that just brush along the top of the tag - return z < zRef and not PathGeom.isRoughly(z, zRef, 0.01) + return z < zRef and not Path.Geom.isRoughly(z, zRef, 0.01) if self.enabled: zFirst = edge.valueAt(edge.FirstParameter).z @@ -298,20 +296,20 @@ class MapWireToTag: self.maxZ = maxZ self.hSpeed = hSpeed self.vSpeed = vSpeed - if PathGeom.pointsCoincide(edge.valueAt(edge.FirstParameter), i): + if Path.Geom.pointsCoincide(edge.valueAt(edge.FirstParameter), i): tail = edge self.commands = [] debugEdge(tail, ".........=") - elif PathGeom.pointsCoincide(edge.valueAt(edge.LastParameter), i): + elif Path.Geom.pointsCoincide(edge.valueAt(edge.LastParameter), i): debugEdge(edge, "++++++++ .") - self.commands = PathGeom.cmdsForEdge( + self.commands = Path.Geom.cmdsForEdge( edge, segm=segm, hSpeed=self.hSpeed, vSpeed=self.vSpeed ) tail = None else: - e, tail = PathGeom.splitEdgeAt(edge, i) + e, tail = Path.Geom.splitEdgeAt(edge, i) debugEdge(e, "++++++++ .") - self.commands = PathGeom.cmdsForEdge( + self.commands = Path.Geom.cmdsForEdge( e, segm=segm, hSpeed=self.hSpeed, vSpeed=self.vSpeed ) debugEdge(tail, ".........-") @@ -320,11 +318,11 @@ class MapWireToTag: self.edges = [] self.entry = i if tail: - PathLog.debug( + Path.Log.debug( "MapWireToTag(%s - %s)" % (i, tail.valueAt(tail.FirstParameter)) ) else: - PathLog.debug("MapWireToTag(%s - )" % i) + Path.Log.debug("MapWireToTag(%s - )" % i) self.complete = False self.haveProblem = False @@ -345,32 +343,32 @@ class MapWireToTag: self.edges.append(edge) def needToFlipEdge(self, edge, p): - if PathGeom.pointsCoincide(edge.valueAt(edge.LastParameter), p): + if Path.Geom.pointsCoincide(edge.valueAt(edge.LastParameter), p): return True, edge.valueAt(edge.FirstParameter) return False, edge.valueAt(edge.LastParameter) def isEntryOrExitStrut(self, e): p1 = e.valueAt(e.FirstParameter) p2 = e.valueAt(e.LastParameter) - if PathGeom.pointsCoincide(p1, self.entry) and p2.z >= self.entry.z: + if Path.Geom.pointsCoincide(p1, self.entry) and p2.z >= self.entry.z: return 1 - if PathGeom.pointsCoincide(p2, self.entry) and p1.z >= self.entry.z: + if Path.Geom.pointsCoincide(p2, self.entry) and p1.z >= self.entry.z: return 1 - if PathGeom.pointsCoincide(p1, self.exit) and p2.z >= self.exit.z: + if Path.Geom.pointsCoincide(p1, self.exit) and p2.z >= self.exit.z: return 2 - if PathGeom.pointsCoincide(p2, self.exit) and p1.z >= self.exit.z: + if Path.Geom.pointsCoincide(p2, self.exit) and p1.z >= self.exit.z: return 2 return 0 def cleanupEdges(self, edges): # want to remove all edges from the wire itself, and all internal struts - PathLog.track("+cleanupEdges") - PathLog.debug(" edges:") + Path.Log.track("+cleanupEdges") + Path.Log.debug(" edges:") if not edges: return edges for e in edges: debugEdge(e, " ") - PathLog.debug(":") + Path.Log.debug(":") self.edgesCleanup = [copy.copy(edges)] # remove any edge that has a point inside the tag solid @@ -384,16 +382,16 @@ class MapWireToTag: self.edgePoints.append(p1) self.edgePoints.append(p2) if self.tag.solid.isInside( - p1, PathGeom.Tolerance, False - ) or self.tag.solid.isInside(p2, PathGeom.Tolerance, False): + p1, Path.Geom.Tolerance, False + ) or self.tag.solid.isInside(p2, Path.Geom.Tolerance, False): edges.remove(e) debugEdge(e, "......... X0", False) else: - if PathGeom.pointsCoincide(p1, self.entry) or PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide(p1, self.entry) or Path.Geom.pointsCoincide( p2, self.entry ): self.entryEdges.append(e) - if PathGeom.pointsCoincide(p1, self.exit) or PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide(p1, self.exit) or Path.Geom.pointsCoincide( p2, self.exit ): self.exitEdges.append(e) @@ -402,23 +400,23 @@ class MapWireToTag: # if there are no edges connected to entry/exit, it means the plunge in/out is vertical # we need to add in the missing segment and collect the new entry/exit edges. if not self.entryEdges: - PathLog.debug("fill entryEdges ...") + Path.Log.debug("fill entryEdges ...") self.realEntry = sorted( self.edgePoints, key=lambda p: (p - self.entry).Length )[0] self.entryEdges = list( - [e for e in edges if PathGeom.edgeConnectsTo(e, self.realEntry)] + [e for e in edges if Path.Geom.edgeConnectsTo(e, self.realEntry)] ) edges.append(Part.Edge(Part.LineSegment(self.entry, self.realEntry))) else: self.realEntry = None if not self.exitEdges: - PathLog.debug("fill exitEdges ...") + Path.Log.debug("fill exitEdges ...") self.realExit = sorted( self.edgePoints, key=lambda p: (p - self.exit).Length )[0] self.exitEdges = list( - [e for e in edges if PathGeom.edgeConnectsTo(e, self.realExit)] + [e for e in edges if Path.Geom.edgeConnectsTo(e, self.realExit)] ) edges.append(Part.Edge(Part.LineSegment(self.realExit, self.exit))) else: @@ -451,7 +449,7 @@ class MapWireToTag: return edges def orderAndFlipEdges(self, inputEdges): - PathLog.track( + Path.Log.track( "entry(%.2f, %.2f, %.2f), exit(%.2f, %.2f, %.2f)" % ( self.entry.x, @@ -472,15 +470,15 @@ class MapWireToTag: for e in copy.copy(edges): p1 = e.valueAt(e.FirstParameter) p2 = e.valueAt(e.LastParameter) - if PathGeom.pointsCoincide(p1, p0): + if Path.Geom.pointsCoincide(p1, p0): outputEdges.append((e, False)) edges.remove(e) lastP = None p0 = p2 debugEdge(e, ">>>>> no flip") break - elif PathGeom.pointsCoincide(p2, p0): - flipped = PathGeom.flipEdge(e) + elif Path.Geom.pointsCoincide(p2, p0): + flipped = Path.Geom.flipEdge(e) if not flipped is None: outputEdges.append((flipped, True)) else: @@ -493,7 +491,7 @@ class MapWireToTag: ) cnt = cnt + 1 p0 = p - PathLog.info("replaced edge with %d straight segments" % cnt) + Path.Log.info("replaced edge with %d straight segments" % cnt) edges.remove(e) lastP = None p0 = p1 @@ -505,43 +503,43 @@ class MapWireToTag: if lastP == p0: self.edgesOrder.append(outputEdges) self.edgesOrder.append(edges) - PathLog.debug("input edges:") + Path.Log.debug("input edges:") for e in inputEdges: debugEdge(e, " ", False) - PathLog.debug("ordered edges:") + Path.Log.debug("ordered edges:") for e, flip in outputEdges: debugEdge(e, " %c " % ("<" if flip else ">"), False) - PathLog.debug("remaining edges:") + Path.Log.debug("remaining edges:") for e in edges: debugEdge(e, " ", False) raise ValueError("No connection to %s" % (p0)) elif lastP: - PathLog.debug( + Path.Log.debug( "xxxxxx (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f)" % (p0.x, p0.y, p0.z, lastP.x, lastP.y, lastP.z) ) else: - PathLog.debug("xxxxxx (%.2f, %.2f, %.2f) -" % (p0.x, p0.y, p0.z)) + Path.Log.debug("xxxxxx (%.2f, %.2f, %.2f) -" % (p0.x, p0.y, p0.z)) lastP = p0 - PathLog.track("-") + Path.Log.track("-") return outputEdges def isStrut(self, edge): - p1 = PathGeom.xy(edge.valueAt(edge.FirstParameter)) - p2 = PathGeom.xy(edge.valueAt(edge.LastParameter)) - return PathGeom.pointsCoincide(p1, p2) + p1 = Path.Geom.xy(edge.valueAt(edge.FirstParameter)) + p2 = Path.Geom.xy(edge.valueAt(edge.LastParameter)) + return Path.Geom.pointsCoincide(p1, p2) def shell(self): if len(self.edges) > 1: wire = Part.Wire(self.initialEdge) else: edge = self.edges[0] - if PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide( edge.valueAt(edge.FirstParameter), self.finalEdge.valueAt(self.finalEdge.FirstParameter), ): wire = Part.Wire(self.finalEdge) - elif hasattr(self, "initialEdge") and PathGeom.pointsCoincide( + elif hasattr(self, "initialEdge") and Path.Geom.pointsCoincide( edge.valueAt(edge.FirstParameter), self.initialEdge.valueAt(self.initialEdge.FirstParameter), ): @@ -550,7 +548,7 @@ class MapWireToTag: wire = Part.Wire(edge) for edge in self.edges[1:]: - if PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide( edge.valueAt(edge.FirstParameter), self.finalEdge.valueAt(self.finalEdge.FirstParameter), ): @@ -559,7 +557,7 @@ class MapWireToTag: wire.add(edge) shell = wire.extrude(FreeCAD.Vector(0, 0, self.tag.height + 1)) - nullFaces = list([f for f in shell.Faces if PathGeom.isRoughly(f.Area, 0)]) + nullFaces = list([f for f in shell.Faces if Path.Geom.isRoughly(f.Area, 0)]) if nullFaces: return shell.removeShape(nullFaces) return shell @@ -576,8 +574,8 @@ class MapWireToTag: p2 = e.valueAt(e.LastParameter) if ( self.tag.isSquare - and (PathGeom.isRoughly(p1.z, self.maxZ) or p1.z > self.maxZ) - and (PathGeom.isRoughly(p2.z, self.maxZ) or p2.z > self.maxZ) + and (Path.Geom.isRoughly(p1.z, self.maxZ) or p1.z > self.maxZ) + and (Path.Geom.isRoughly(p2.z, self.maxZ) or p2.z > self.maxZ) ): rapid = p1 if flip else p2 else: @@ -589,7 +587,7 @@ class MapWireToTag: ) rapid = None commands.extend( - PathGeom.cmdsForEdge( + Path.Geom.cmdsForEdge( e, False, False, @@ -605,7 +603,7 @@ class MapWireToTag: # rapid = None # commented out per LGTM suggestion return commands except Exception as e: - PathLog.error( + Path.Log.error( "Exception during processing tag @(%.2f, %.2f) (%s) - disabling the tag" % (self.tag.x, self.tag.y, e.args[0]) ) @@ -613,7 +611,7 @@ class MapWireToTag: commands = [] for e in self.edges: commands.extend( - PathGeom.cmdsForEdge(e, hSpeed=self.hSpeed, vSpeed=self.vSpeed) + Path.Geom.cmdsForEdge(e, hSpeed=self.hSpeed, vSpeed=self.vSpeed) ) return commands return [] @@ -622,9 +620,9 @@ class MapWireToTag: self.tail = None self.finalEdge = edge if self.tag.solid.isInside( - edge.valueAt(edge.LastParameter), PathGeom.Tolerance, True + edge.valueAt(edge.LastParameter), Path.Geom.Tolerance, True ): - PathLog.track("solid.isInside") + Path.Log.track("solid.isInside") self.addEdge(edge) else: i = self.tag.intersects(edge, edge.LastParameter) @@ -632,14 +630,14 @@ class MapWireToTag: self.offendingEdge = edge debugEdge(edge, "offending Edge:", False) o = self.tag.originAt(self.tag.z) - PathLog.debug("originAt: (%.2f, %.2f, %.2f)" % (o.x, o.y, o.z)) + Path.Log.debug("originAt: (%.2f, %.2f, %.2f)" % (o.x, o.y, o.z)) i = edge.valueAt(edge.FirstParameter) - if PathGeom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)): - PathLog.track("tail") + if Path.Geom.pointsCoincide(i, edge.valueAt(edge.FirstParameter)): + Path.Log.track("tail") self.tail = edge else: - PathLog.track("split") - e, tail = PathGeom.splitEdgeAt(edge, i) + Path.Log.track("split") + e, tail = Path.Geom.splitEdgeAt(edge, i) self.addEdge(e) self.tail = tail self.exit = i @@ -662,12 +660,12 @@ class _RapidEdges: r0 = r.Vertexes[0] r1 = r.Vertexes[1] if ( - PathGeom.isRoughly(r0.X, v0.X) - and PathGeom.isRoughly(r0.Y, v0.Y) - and PathGeom.isRoughly(r0.Z, v0.Z) - and PathGeom.isRoughly(r1.X, v1.X) - and PathGeom.isRoughly(r1.Y, v1.Y) - and PathGeom.isRoughly(r1.Z, v1.Z) + Path.Geom.isRoughly(r0.X, v0.X) + and Path.Geom.isRoughly(r0.Y, v0.Y) + and Path.Geom.isRoughly(r0.Z, v0.Z) + and Path.Geom.isRoughly(r1.X, v1.X) + and Path.Geom.isRoughly(r1.Y, v1.Y) + and Path.Geom.isRoughly(r1.Z, v1.Z) ): return True return False @@ -675,9 +673,9 @@ class _RapidEdges: class PathData: def __init__(self, obj): - PathLog.track(obj.Base.Name) + Path.Log.track(obj.Base.Name) self.obj = obj - self.wire, rapid = PathGeom.wireForPath(obj.Base.Path) + self.wire, rapid = Path.Geom.wireForPath(obj.Base.Path) self.rapid = _RapidEdges(rapid) if self.wire: self.edges = self.wire.Edges @@ -692,8 +690,8 @@ class PathData: bottom = [ e for e in edges - if PathGeom.isRoughly(e.Vertexes[0].Point.z, minZ) - and PathGeom.isRoughly(e.Vertexes[1].Point.z, minZ) + if Path.Geom.isRoughly(e.Vertexes[0].Point.z, minZ) + and Path.Geom.isRoughly(e.Vertexes[1].Point.z, minZ) ] self.bottomEdges = bottom try: @@ -727,7 +725,7 @@ class PathData: def generateTags( self, obj, count, width=None, height=None, angle=None, radius=None, spacing=None ): - PathLog.track(count, width, height, angle, spacing) + Path.Log.track(count, width, height, angle, spacing) # for e in self.baseWire.Edges: # debugMarker(e.Vertexes[0].Point, 'base', (0.0, 1.0, 1.0), 0.2) @@ -746,8 +744,8 @@ class PathData: startIndex = 0 for i in range(0, len(self.baseWire.Edges)): edge = self.baseWire.Edges[i] - PathLog.debug(" %d: %.2f" % (i, edge.Length)) - if PathGeom.isRoughly(edge.Length, longestEdge.Length): + Path.Log.debug(" %d: %.2f" % (i, edge.Length)) + if Path.Geom.isRoughly(edge.Length, longestEdge.Length): startIndex = i break @@ -761,7 +759,7 @@ class PathData: minLength = min(2.0 * W, longestEdge.Length) - PathLog.debug( + Path.Log.debug( "length=%.2f shortestEdge=%.2f(%.2f) longestEdge=%.2f(%.2f) minLength=%.2f" % ( self.baseWire.Length, @@ -772,12 +770,12 @@ class PathData: minLength, ) ) - PathLog.debug( + Path.Log.debug( " start: index=%-2d count=%d (length=%.2f, distance=%.2f)" % (startIndex, startCount, startEdge.Length, tagDistance) ) - PathLog.debug(" -> lastTagLength=%.2f)" % lastTagLength) - PathLog.debug(" -> currentLength=%.2f)" % currentLength) + Path.Log.debug(" -> lastTagLength=%.2f)" % lastTagLength) + Path.Log.debug(" -> currentLength=%.2f)" % currentLength) edgeDict = {startIndex: startCount} @@ -796,7 +794,7 @@ class PathData: for (i, count) in PathUtil.keyValueIter(edgeDict): edge = self.baseWire.Edges[i] - PathLog.debug(" %d: %d" % (i, count)) + Path.Log.debug(" %d: %d" % (i, count)) # debugMarker(edge.Vertexes[0].Point, 'base', (1.0, 0.0, 0.0), 0.2) # debugMarker(edge.Vertexes[1].Point, 'base', (0.0, 1.0, 0.0), 0.2) if 0 != count: @@ -836,12 +834,12 @@ class PathData: tags.append(Tag(j, at.x, at.y, W, H, A, R, True)) j += 1 else: - PathLog.warning( + Path.Log.warning( "Tag[%d] (%.2f, %.2f, %.2f) is too far away to copy: %.2f (%.2f)" % (i, pos.x, pos.y, self.minZ, dist[0], W) ) else: - PathLog.info("tag[%d]: not enabled, skipping" % i) + Path.Log.info("tag[%d]: not enabled, skipping" % i) print("copied %d tags" % len(tags)) return tags @@ -862,10 +860,10 @@ class PathData: tagCount += 1 lastTagLength += tagDistance if tagCount > 0: - PathLog.debug(" index=%d -> count=%d" % (index, tagCount)) + Path.Log.debug(" index=%d -> count=%d" % (index, tagCount)) edgeDict[index] = tagCount else: - PathLog.debug(" skipping=%-2d (%.2f)" % (index, edge.Length)) + Path.Log.debug(" skipping=%-2d (%.2f)" % (index, edge.Length)) return (currentLength, lastTagLength) @@ -899,7 +897,7 @@ class PathData: ts = [ t for t in tags - if PathGeom.isRoughly( + if Path.Geom.isRoughly( 0, Part.Vertex(t.originAt(self.minZ)).distToShape(edge)[0], 0.1 ) ] @@ -913,7 +911,7 @@ class PathData: ordered.append(t) # disable all tags that are not on the base wire. for tag in tags: - PathLog.info( + Path.Log.info( "Tag #%d (%.2f, %.2f, %.2f) not on base wire - disabling\n" % (len(ordered), tag.x, tag.y, self.minZ) ) @@ -923,11 +921,11 @@ class PathData: def pointIsOnPath(self, p): v = Part.Vertex(self.pointAtBottom(p)) - PathLog.debug("pt = (%f, %f, %f)" % (v.X, v.Y, v.Z)) + Path.Log.debug("pt = (%f, %f, %f)" % (v.X, v.Y, v.Z)) for e in self.bottomEdges: indent = "{} ".format(e.distToShape(v)[0]) debugEdge(e, indent, True) - if PathGeom.isRoughly(0.0, v.distToShape(e)[0], 0.1): + if Path.Geom.isRoughly(0.0, v.distToShape(e)[0], 0.1): return True return False @@ -1060,18 +1058,18 @@ class ObjectTagDressup: return False def isValidTagStartIntersection(self, edge, i): - if PathGeom.pointsCoincide(i, edge.valueAt(edge.LastParameter)): + if Path.Geom.pointsCoincide(i, edge.valueAt(edge.LastParameter)): return False p1 = edge.valueAt(edge.FirstParameter) p2 = edge.valueAt(edge.LastParameter) - if PathGeom.pointsCoincide(PathGeom.xy(p1), PathGeom.xy(p2)): + if Path.Geom.pointsCoincide(Path.Geom.xy(p1), Path.Geom.xy(p2)): # if this vertical goes up, it can't be the start of a tag intersection if p1.z < p2.z: return False return True def createPath(self, obj, pathData, tags): - PathLog.track() + Path.Log.track() commands = [] lastEdge = 0 lastTag = 0 @@ -1097,7 +1095,7 @@ class ObjectTagDressup: vertRapid = tc.VertRapid.Value while edge or lastEdge < len(pathData.edges): - PathLog.debug( + Path.Log.debug( "------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags)) ) if not edge: @@ -1142,9 +1140,9 @@ class ObjectTagDressup: v = edge.Vertexes[1] if ( not commands - and PathGeom.isRoughly(0, v.X) - and PathGeom.isRoughly(0, v.Y) - and not PathGeom.isRoughly(0, v.Z) + and Path.Geom.isRoughly(0, v.X) + and Path.Geom.isRoughly(0, v.Y) + and not Path.Geom.isRoughly(0, v.Z) ): # The very first move is just to move to ClearanceHeight commands.append( @@ -1158,7 +1156,7 @@ class ObjectTagDressup: ) else: commands.extend( - PathGeom.cmdsForEdge( + Path.Geom.cmdsForEdge( edge, segm=segm, hSpeed=horizFeed, vSpeed=vertFeed ) ) @@ -1194,26 +1192,26 @@ class ObjectTagDressup: if tag.enabled: if prev: if prev.solid.common(tag.solid).Faces: - PathLog.info( + Path.Log.info( "Tag #%d intersects with previous tag - disabling\n" % i ) - PathLog.debug("this tag = %d [%s]" % (i, tag.solid.BoundBox)) + Path.Log.debug("this tag = %d [%s]" % (i, tag.solid.BoundBox)) tag.enabled = False elif self.pathData.edges: e = self.pathData.edges[0] p0 = e.valueAt(e.FirstParameter) p1 = e.valueAt(e.LastParameter) if tag.solid.isInside( - p0, PathGeom.Tolerance, True - ) or tag.solid.isInside(p1, PathGeom.Tolerance, True): - PathLog.info( + p0, Path.Geom.Tolerance, True + ) or tag.solid.isInside(p1, Path.Geom.Tolerance, True): + Path.Log.info( "Tag #%d intersects with starting point - disabling\n" % i ) tag.enabled = False if tag.enabled: prev = tag - PathLog.debug("previousTag = %d [%s]" % (i, prev)) + Path.Log.debug("previousTag = %d [%s]" % (i, prev)) else: disabled.append(i) tag.nr = i # assign final nr @@ -1241,7 +1239,7 @@ class ObjectTagDressup: pathData = self.setup(obj) if not pathData: - PathLog.debug("execute - no pathData") + Path.Log.debug("execute - no pathData") return self.tags = [] @@ -1250,21 +1248,21 @@ class ObjectTagDressup: obj, obj.Positions, obj.Disabled ) if obj.Disabled != disabled: - PathLog.debug( + Path.Log.debug( "Updating properties.... %s vs. %s" % (obj.Disabled, disabled) ) obj.Positions = positions obj.Disabled = disabled if not self.tags: - PathLog.debug("execute - no tags") + Path.Log.debug("execute - no tags") obj.Path = obj.Base.Path return try: self.processTags(obj) except Exception as e: - PathLog.error( + Path.Log.error( "processing tags failed clearing all tags ... '%s'" % (e.args[0]) ) obj.Path = obj.Base.Path @@ -1283,15 +1281,15 @@ class ObjectTagDressup: @waiting_effects def processTags(self, obj): tagID = 0 - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: for tag in self.tags: tagID += 1 if tag.enabled: - PathLog.debug( + Path.Log.debug( "x=%s, y=%s, z=%s" % (tag.x, tag.y, self.pathData.minZ) ) # debugMarker(FreeCAD.Vector(tag.x, tag.y, self.pathData.minZ), "tag-%02d" % tagID , (1.0, 0.0, 1.0), 0.5) - # if not PathGeom.isRoughly(90, tag.angle): + # if not Path.Geom.isRoughly(90, tag.angle): # debugCone(tag.originAt(self.pathData.minZ), tag.r1, tag.r2, tag.actualHeight, "tag-%02d" % tagID) # else: # debugCylinder(tag.originAt(self.pathData.minZ), tag.fullWidth()/2, tag.actualHeight, "tag-%02d" % tagID) @@ -1299,12 +1297,12 @@ class ObjectTagDressup: obj.Path = self.createPath(obj, self.pathData, self.tags) def setup(self, obj, generate=False): - PathLog.debug("setup") + Path.Log.debug("setup") self.obj = obj try: pathData = PathData(obj) except ValueError: - PathLog.error( + Path.Log.error( translate( "Path_DressupTag", "Cannot insert holding tags for this path - please select a Profile path", @@ -1325,7 +1323,7 @@ class ObjectTagDressup: return self.pathData def setXyEnabled(self, triples): - PathLog.track() + Path.Log.track() if not self.pathData: self.setup(self.obj) positions = [] @@ -1358,13 +1356,13 @@ def Create(baseObject, name="DressupTag"): Create(basePath, name='DressupTag') ... create tag dressup object for the given base path. """ if not baseObject.isDerivedFrom("Path::Feature"): - PathLog.error( + Path.Log.error( translate("Path_DressupTag", "The selected object is not a path") + "\n" ) return None if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): - PathLog.error(translate("Path_DressupTag", "Please select a Profile object")) + Path.Log.error(translate("Path_DressupTag", "Please select a Profile object")) return None obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) @@ -1375,4 +1373,4 @@ def Create(baseObject, name="DressupTag"): return obj -PathLog.notice("Loading Path_DressupTag... done\n") +Path.Log.notice("Loading Path_DressupTag... done\n") diff --git a/src/Mod/Path/PathScripts/PathDressup.py b/src/Mod/Path/Path/Dressup/Utils.py similarity index 98% rename from src/Mod/Path/PathScripts/PathDressup.py rename to src/Mod/Path/Path/Dressup/Utils.py index cec69a65fc..3927f77bdf 100644 --- a/src/Mod/Path/PathScripts/PathDressup.py +++ b/src/Mod/Path/Path/Dressup/Utils.py @@ -21,7 +21,7 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathJob as PathJob +import Path.Main.Job as PathJob def selection(): diff --git a/src/Mod/Path/Path/Dressup/__init__.py b/src/Mod/Path/Path/Dressup/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/PathGeom.py b/src/Mod/Path/Path/Geom.py similarity index 95% rename from src/Mod/Path/PathScripts/PathGeom.py rename to src/Mod/Path/Path/Geom.py index 1486c73496..29955f6f25 100644 --- a/src/Mod/Path/PathScripts/PathGeom.py +++ b/src/Mod/Path/Path/Geom.py @@ -23,7 +23,6 @@ import FreeCAD import Path -import PathScripts.PathLog as PathLog import math from FreeCAD import Vector @@ -34,7 +33,7 @@ from lazy_loader.lazy_loader import LazyLoader Part = LazyLoader("Part", globals(), "Part") -__title__ = "PathGeom - geometry utilities for Path" +__title__ = "Geom - geometry utilities for Path" __author__ = "sliptonic (Brad Collette)" __url__ = "https://www.freecadweb.org" __doc__ = "Functions to extract and convert between Path.Command and Part.Edge and utility functions to reason about them." @@ -44,10 +43,10 @@ Tolerance = 0.000001 translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class Side: @@ -170,7 +169,7 @@ def isVertical(obj): if type(obj.Surface) == Part.SurfaceOfRevolution: return isHorizontal(obj.Surface.Direction) if type(obj.Surface) != Part.BSplineSurface: - PathLog.info( + Path.Log.info( translate("PathGeom", "face %s not handled, assuming not vertical") % type(obj.Surface) ) @@ -187,13 +186,13 @@ def isVertical(obj): # the current assumption is that a bezier curve is vertical if its end points are vertical return isVertical(obj.Curve.EndPoint - obj.Curve.StartPoint) if type(obj.Curve) != Part.BSplineCurve: - PathLog.info( + Path.Log.info( translate("PathGeom", "edge %s not handled, assuming not vertical") % type(obj.Curve) ) return None - PathLog.error(translate("PathGeom", "isVertical(%s) not supported") % obj) + Path.Log.error(translate("PathGeom", "isVertical(%s) not supported") % obj) return None @@ -224,7 +223,7 @@ def isHorizontal(obj): return isVertical(obj.Curve.Axis) return isRoughly(obj.BoundBox.ZLength, 0.0) - PathLog.error(translate("PathGeom", "isHorizontal(%s) not supported") % obj) + Path.Log.error(translate("PathGeom", "isHorizontal(%s) not supported") % obj) return None @@ -258,7 +257,7 @@ def speedBetweenPoints(p0, p1, hSpeed, vSpeed): pitch = pitch + 1 while pitch > 1: pitch = pitch - 1 - PathLog.debug( + Path.Log.debug( " pitch = %g %g (%.2f, %.2f, %.2f) -> %.2f" % (pitch, math.atan2(xy(d).Length, d.z), d.x, d.y, d.z, xy(d).Length) ) @@ -322,7 +321,7 @@ def cmdsForEdge(edge, flip=False, useHelixForBSpline=True, segm=50, hSpeed=0, vS offset = edge.Curve.Center - pt else: pd = Part.Circle(xy(p1), xy(p2), xy(p3)).Center - PathLog.debug( + Path.Log.debug( "**** %s.%d: (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) -> center=(%.2f, %.2f)" % ( cmd, @@ -347,15 +346,15 @@ def cmdsForEdge(edge, flip=False, useHelixForBSpline=True, segm=50, hSpeed=0, vS pc = xy(p3) offset = Part.Circle(pa, pb, pc).Center - pa - PathLog.debug( + Path.Log.debug( "**** (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (pa.x, pa.y, pa.z, pc.x, pc.y, pc.z) ) - PathLog.debug( + Path.Log.debug( "**** (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f)" % (pb.x, pb.y, pb.z, pd.x, pd.y, pd.z) ) - PathLog.debug("**** (%.2f, %.2f, %.2f)" % (offset.x, offset.y, offset.z)) + Path.Log.debug("**** (%.2f, %.2f, %.2f)" % (offset.x, offset.y, offset.z)) params.update({"I": offset.x, "J": offset.y, "K": (p3.z - p1.z) / 2}) # G2/G3 commands are always performed at hSpeed @@ -389,8 +388,8 @@ def edgeForCmd(cmd, startPoint): """edgeForCmd(cmd, startPoint). Returns an Edge representing the given command, assuming a given startPoint.""" - PathLog.debug("cmd: {}".format(cmd)) - PathLog.debug("startpoint {}".format(startPoint)) + Path.Log.debug("cmd: {}".format(cmd)) + Path.Log.debug("startpoint {}".format(startPoint)) endPoint = commandEndPoint(cmd, startPoint) if (cmd.Name in CmdMoveStraight) or (cmd.Name in CmdMoveRapid): @@ -405,7 +404,7 @@ def edgeForCmd(cmd, startPoint): d = -B.x * A.y + B.y * A.x if isRoughly(d, 0, 0.005): - PathLog.debug( + Path.Log.debug( "Half circle arc at: (%.2f, %.2f, %.2f)" % (center.x, center.y, center.z) ) @@ -416,23 +415,23 @@ def edgeForCmd(cmd, startPoint): else: C = A + B angle = getAngle(C) - PathLog.debug( + Path.Log.debug( "Arc (%8f) at: (%.2f, %.2f, %.2f) -> angle=%f" % (d, center.x, center.y, center.z, angle / math.pi) ) R = A.Length - PathLog.debug( + Path.Log.debug( "arc: p1=(%.2f, %.2f) p2=(%.2f, %.2f) -> center=(%.2f, %.2f)" % (startPoint.x, startPoint.y, endPoint.x, endPoint.y, center.x, center.y) ) - PathLog.debug( + Path.Log.debug( "arc: A=(%.2f, %.2f) B=(%.2f, %.2f) -> d=%.2f" % (A.x, A.y, B.x, B.y, d) ) - PathLog.debug("arc: R=%.2f angle=%.2f" % (R, angle / math.pi)) + Path.Log.debug("arc: R=%.2f angle=%.2f" % (R, angle / math.pi)) if isRoughly(startPoint.z, endPoint.z): midPoint = center + Vector(math.cos(angle), math.sin(angle), 0) * R - PathLog.debug( + Path.Log.debug( "arc: (%.2f, %.2f) -> (%.2f, %.2f) -> (%.2f, %.2f)" % ( startPoint.x, @@ -443,9 +442,9 @@ def edgeForCmd(cmd, startPoint): endPoint.y, ) ) - PathLog.debug("StartPoint:{}".format(startPoint)) - PathLog.debug("MidPoint:{}".format(midPoint)) - PathLog.debug("EndPoint:{}".format(endPoint)) + Path.Log.debug("StartPoint:{}".format(startPoint)) + Path.Log.debug("MidPoint:{}".format(midPoint)) + Path.Log.debug("EndPoint:{}".format(endPoint)) if pointsCoincide(startPoint, endPoint, 0.001): return Part.makeCircle(R, center, FreeCAD.Vector(0, 0, 1)) @@ -582,10 +581,10 @@ def combineConnectedShapes(shapes): while not done: done = True combined = [] - PathLog.debug("shapes: {}".format(shapes)) + Path.Log.debug("shapes: {}".format(shapes)) for shape in shapes: connected = [f for f in combined if isRoughly(shape.distToShape(f)[0], 0.0)] - PathLog.debug( + Path.Log.debug( " {}: connected: {} dist: {}".format( len(combined), connected, @@ -672,7 +671,7 @@ def flipEdge(edge): elif type(edge.Curve) == Part.OffsetCurve: return edge.reversed() - PathLog.warning( + Path.Log.warning( translate("PathGeom", "%s not supported for flipping") % type(edge.Curve) ) @@ -681,7 +680,7 @@ def flipWire(wire): """Flip the entire wire and all its edges so it is being processed the other way around.""" edges = [flipEdge(e) for e in wire.Edges] edges.reverse() - PathLog.debug(edges) + Path.Log.debug(edges) return Part.Wire(edges) @@ -710,7 +709,7 @@ def combineHorizontalFaces(faces): The Adaptive op is not concerned with which hole edges belong to which face. Attempts to do the same shape connecting failed with TechDraw.findShapeOutline() and - PathGeom.combineConnectedShapes(), so this algorithm was created. + Path.Geom.combineConnectedShapes(), so this algorithm was created. """ horizontal = list() offset = 10.0 @@ -729,7 +728,7 @@ def combineHorizontalFaces(faces): "PathGeom", "Zero working area to process. Check your selection and settings.", ) - PathLog.info(msg) + Path.Log.info(msg) return horizontal afbb = allFaces.BoundBox diff --git a/src/Mod/Path/PathScripts/PathGuiInit.py b/src/Mod/Path/Path/GuiInit.py similarity index 51% rename from src/Mod/Path/PathScripts/PathGuiInit.py rename to src/Mod/Path/Path/GuiInit.py index 3ad0db2b42..b57207240b 100644 --- a/src/Mod/Path/PathScripts/PathGuiInit.py +++ b/src/Mod/Path/Path/GuiInit.py @@ -20,16 +20,16 @@ # * * # *************************************************************************** -import PathScripts.PathLog as PathLog +import Path import subprocess LOGLEVEL = False if LOGLEVEL: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) Processed = False @@ -37,46 +37,47 @@ Processed = False def Startup(): global Processed if not Processed: - PathLog.debug("Initializing PathGui") - from PathScripts import PathAdaptiveGui - from PathScripts import PathArray - from PathScripts import PathComment - from PathScripts import PathCustomGui - from PathScripts import PathDeburrGui - from PathScripts import PathDressupAxisMap - from PathScripts import PathDressupDogbone - from PathScripts import PathDressupDragknife - from PathScripts import PathDressupLeadInOut - from PathScripts import PathDressupPathBoundaryGui - from PathScripts import PathDressupRampEntry - from PathScripts import PathDressupTagGui - from PathScripts import PathDressupZCorrect - from PathScripts import PathDrillingGui - from PathScripts import PathEngraveGui - from PathScripts import PathFixture - from PathScripts import PathHelixGui - from PathScripts import PathHop - from PathScripts import PathInspect - from PathScripts import PathMillFaceGui - from PathScripts import PathPocketGui - from PathScripts import PathPocketShapeGui - from PathScripts import PathPost - from PathScripts import PathProbeGui - from PathScripts import PathProfileGui - from PathScripts import PathPropertyBagGui - from PathScripts import PathSanity - from PathScripts import PathSetupSheetGui - from PathScripts import PathSimpleCopy - from PathScripts import PathSimulatorGui - from PathScripts import PathSlotGui - from PathScripts import PathStop - from PathScripts import PathThreadMillingGui - from PathScripts import PathToolController - from PathScripts import PathToolControllerGui - from PathScripts import PathToolLibraryEditor - from PathScripts import PathToolLibraryManager + Path.Log.debug("Initializing PathGui") + from Path.Base.Gui import PropertyBag + from Path.Base.Gui import SetupSheet + from Path.Dressup.Gui import AxisMap + from Path.Dressup.Gui import Dogbone + from Path.Dressup.Gui import Dragknife + from Path.Dressup.Gui import LeadInOut + from Path.Dressup.Gui import Boundary + from Path.Dressup.Gui import RampEntry + from Path.Dressup.Gui import Tags + from Path.Dressup.Gui import ZCorrect + + from Path.Main.Gui import Fixture + from Path.Main.Gui import Inspect + from Path.Main.Gui import Sanity + from Path.Main.Gui import Simulator + + from Path.Op.Gui import Adaptive + from Path.Op.Gui import Array + from Path.Op.Gui import Comment + from Path.Op.Gui import Custom + from Path.Op.Gui import Deburr + from Path.Op.Gui import Drilling + from Path.Op.Gui import Engrave + from Path.Op.Gui import Helix + from Path.Op.Gui import Hop + from Path.Op.Gui import MillFace + from Path.Op.Gui import Pocket + from Path.Op.Gui import PocketShape + from Path.Op.Gui import Probe + from Path.Op.Gui import Profile + from Path.Op.Gui import SimpleCopy + from Path.Op.Gui import Slot + from Path.Op.Gui import Stop + from Path.Op.Gui import ThreadMilling + from Path.Op.Gui import Vcarve + from Path.Post import Command + from Path.Tool import Controller + from Path.Tool.Gui import Controller + from PathScripts import PathUtilsGui - from PathScripts import PathVcarveGui from packaging.version import Version, parse @@ -92,10 +93,10 @@ def Startup(): v = parse(r.decode("utf-8")) if v >= Version("1.2.2"): - from PathScripts import PathCamoticsGui + from Path.Main.Gui import Camotics except (FileNotFoundError, ModuleNotFoundError): pass Processed = True else: - PathLog.debug("Skipping PathGui initialisation") + Path.Log.debug("Skipping PathGui initialisation") diff --git a/src/Mod/Path/PathScripts/PathLog.py b/src/Mod/Path/Path/Log.py similarity index 100% rename from src/Mod/Path/PathScripts/PathLog.py rename to src/Mod/Path/Path/Log.py diff --git a/src/Mod/Path/PathScripts/PathCamoticsGui.py b/src/Mod/Path/Path/Main/Gui/Camotics.py similarity index 94% rename from src/Mod/Path/PathScripts/PathCamoticsGui.py rename to src/Mod/Path/Path/Main/Gui/Camotics.py index f68948a9d7..04416d9fc3 100644 --- a/src/Mod/Path/PathScripts/PathCamoticsGui.py +++ b/src/Mod/Path/Path/Main/Gui/Camotics.py @@ -26,9 +26,9 @@ from threading import Thread, Lock import FreeCAD import FreeCADGui import Mesh +import Path import PathScripts -import PathScripts.PathLog as PathLog -import PathScripts.PathPost as PathPost +import Path.Post.Command as PathPost import camotics import io import json @@ -43,10 +43,10 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Task panel for Camotics Simulation" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -76,7 +76,7 @@ class CAMoticsUI: subprocess.Popen(["camotics", filename]) def makeCamoticsFile(self): - PathLog.track() + Path.Log.track() filename = QtGui.QFileDialog.getSaveFileName( self.form, translate("Path", "Save Project As"), @@ -139,7 +139,7 @@ class CamoticsSimulation(QtCore.QObject): def worker(self, lock): while True: item = self.q.get() - PathLog.debug("worker processing: {}".format(item)) + Path.Log.debug("worker processing: {}".format(item)) with lock: if item["TYPE"] == "STATUS": self.statusChange.emit(item["VALUE"]) @@ -199,7 +199,7 @@ class CamoticsSimulation(QtCore.QObject): ) postlist = PathPost.buildPostList(self.job) - PathLog.track(postlist) + Path.Log.track(postlist) # self.filenames = [PathPost.resolveFileName(self.job)] success = True @@ -217,7 +217,7 @@ class CamoticsSimulation(QtCore.QObject): extraargs="--no-show-editor", ) self.filenames.append(name) - PathLog.track(result, gcode, name) + Path.Log.track(result, gcode, name) if result is None: success = False @@ -231,11 +231,11 @@ class CamoticsSimulation(QtCore.QObject): self.SIM.wait() tot = sum([step["time"] for step in self.SIM.get_path()]) - PathLog.debug("sim time: {}".format(tot)) + Path.Log.debug("sim time: {}".format(tot)) self.taskForm.setRunTime(tot) def execute(self, timeIndex): - PathLog.track() + Path.Log.track() self.SIM.start(self.callback, time=timeIndex, done=self.isDone) def accept(self): @@ -245,7 +245,7 @@ class CamoticsSimulation(QtCore.QObject): pass def buildproject(self): # , files=[]): - PathLog.track() + Path.Log.track() job = self.job @@ -322,7 +322,7 @@ class CommandCamoticsSimulate: return False try: job = FreeCADGui.Selection.getSelectionEx()[0].Object - return isinstance(job.Proxy, PathScripts.PathJob.ObjectJob) + return isinstance(job.Proxy, Path.Main.Job.ObjectJob) except: return False diff --git a/src/Mod/Path/PathScripts/PathFixture.py b/src/Mod/Path/Path/Main/Gui/Fixture.py similarity index 97% rename from src/Mod/Path/PathScripts/PathFixture.py rename to src/Mod/Path/Path/Main/Gui/Fixture.py index 4a847306ff..ed98c73d29 100644 --- a/src/Mod/Path/PathScripts/PathFixture.py +++ b/src/Mod/Path/Path/Main/Gui/Fixture.py @@ -165,16 +165,16 @@ class CommandPathFixture: def Activated(self): FreeCAD.ActiveDocument.openTransaction("Create a Fixture Offset") - FreeCADGui.addModule("PathScripts.PathFixture") + FreeCADGui.addModule("Path.Main.Gui.Fixture") snippet = """ import Path import PathScripts from PathScripts import PathUtils prjexists = False obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Fixture") -PathScripts.PathFixture.Fixture(obj) +Path.Main.Gui.Fixture.Fixture(obj) obj.Active = True -PathScripts.PathFixture._ViewProviderFixture(obj.ViewObject) +Path.Main.Gui.Fixture._ViewProviderFixture(obj.ViewObject) PathUtils.addToJob(obj) diff --git a/src/Mod/Path/PathScripts/PathInspect.py b/src/Mod/Path/Path/Main/Gui/Inspect.py similarity index 98% rename from src/Mod/Path/PathScripts/PathInspect.py rename to src/Mod/Path/Path/Main/Gui/Inspect.py index be63084b7c..63d4e6f7d6 100644 --- a/src/Mod/Path/PathScripts/PathInspect.py +++ b/src/Mod/Path/Path/Main/Gui/Inspect.py @@ -285,9 +285,9 @@ class CommandPathInspect: return # if everything is ok, execute - FreeCADGui.addModule("PathScripts.PathInspect") + FreeCADGui.addModule("Path.Main.Gui.Inspect") FreeCADGui.doCommand( - "PathScripts.PathInspect.show(FreeCAD.ActiveDocument." + "Path.Main.Gui.Inspect.show(FreeCAD.ActiveDocument." + selection[0].Name + ")" ) diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/Path/Main/Gui/Job.py similarity index 93% rename from src/Mod/Path/PathScripts/PathJobGui.py rename to src/Mod/Path/Path/Main/Gui/Job.py index 8727f17ec4..c8cd3285d4 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/Path/Main/Gui/Job.py @@ -27,19 +27,16 @@ from contextlib import contextmanager from pivy import coin import FreeCAD import FreeCADGui -import PathScripts.PathGeom as PathGeom -import PathScripts.PathGuiInit as PathGuiInit -import PathScripts.PathJob as PathJob -import PathScripts.PathJobCmd as PathJobCmd -import PathScripts.PathJobDlg as PathJobDlg -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathSetupSheetGui as PathSetupSheetGui -import PathScripts.PathStock as PathStock -import PathScripts.PathToolBitGui as PathToolBitGui -import PathScripts.PathToolControllerGui as PathToolControllerGui -import PathScripts.PathToolLibraryEditor as PathToolLibraryEditor -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Gui.SetupSheet as PathSetupSheetGui +import Path.Base.Util as PathUtil +import Path.GuiInit as PathGuiInit +import Path.Main.Gui.JobCmd as PathJobCmd +import Path.Main.Gui.JobDlg as PathJobDlg +import Path.Main.Job as PathJob +import Path.Main.Stock as PathStock +import Path.Tool.Gui.Bit as PathToolBitGui +import Path.Tool.Gui.Controller as PathToolControllerGui import PathScripts.PathUtils as PathUtils import json import math @@ -55,10 +52,10 @@ DraftVecUtils = LazyLoader("DraftVecUtils", globals(), "DraftVecUtils") translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def _OpenCloseResourceEditor(obj, vobj, edit): @@ -74,7 +71,7 @@ def _OpenCloseResourceEditor(obj, vobj, edit): missing = "ViewObject" if job.ViewObject: missing = "Proxy" - PathLog.warning("Cannot edit %s - no %s" % (obj.Label, missing)) + Path.Log.warning("Cannot edit %s - no %s" % (obj.Label, missing)) @contextmanager @@ -162,7 +159,7 @@ class ViewProvider: return hasattr(self, "deleteOnReject") and self.deleteOnReject def setEdit(self, vobj=None, mode=0): - PathLog.track(mode) + Path.Log.track(mode) if 0 == mode: job = self.vobj.Object if not job.Proxy.integrityCheck(job): @@ -192,7 +189,7 @@ class ViewProvider: return self.openTaskPanel("Model") if obj == self.obj.Stock: return self.openTaskPanel("Stock") - PathLog.info( + Path.Log.info( "Expected a specific object to edit - %s not recognized" % obj.Label ) return self.openTaskPanel() @@ -221,12 +218,12 @@ class ViewProvider: return children def onDelete(self, vobj, arg2=None): - PathLog.track(vobj.Object.Label, arg2) + Path.Log.track(vobj.Object.Label, arg2) self.obj.Proxy.onDelete(self.obj, arg2) return True def updateData(self, obj, prop): - PathLog.track(obj.Label, prop) + Path.Log.track(obj.Label, prop) # make sure the resource view providers are setup properly if prop == "Model" and self.obj.Model: for base in self.obj.Model.Group: @@ -241,7 +238,7 @@ class ViewProvider: self.obj.Stock.ViewObject.Proxy.onEdit(_OpenCloseResourceEditor) def rememberBaseVisibility(self, obj, base): - PathLog.track() + Path.Log.track() if base.ViewObject: orig = PathUtil.getPublicObject(obj.Proxy.baseObject(obj, base)) self.baseVisibility[base.Name] = ( @@ -254,7 +251,7 @@ class ViewProvider: base.ViewObject.Visibility = True def forgetBaseVisibility(self, obj, base): - PathLog.track() + Path.Log.track() if self.baseVisibility.get(base.Name): visibility = self.baseVisibility[base.Name] visibility[0].ViewObject.Visibility = visibility[1] @@ -262,7 +259,7 @@ class ViewProvider: del self.baseVisibility[base.Name] def setupEditVisibility(self, obj): - PathLog.track() + Path.Log.track() self.baseVisibility = {} for base in obj.Model.Group: self.rememberBaseVisibility(obj, base) @@ -273,14 +270,14 @@ class ViewProvider: self.obj.Stock.ViewObject.Visibility = True def resetEditVisibility(self, obj): - PathLog.track() + Path.Log.track() for base in obj.Model.Group: self.forgetBaseVisibility(obj, base) if obj.Stock and obj.Stock.ViewObject: obj.Stock.ViewObject.Visibility = self.stockVisibility def setupContextMenu(self, vobj, menu): - PathLog.track() + Path.Log.track() for action in menu.actions(): menu.removeAction(action) action = QtGui.QAction(translate("Path_Job", "Edit"), menu) @@ -293,7 +290,7 @@ class StockEdit(object): StockType = PathStock.StockType.Unknown def __init__(self, obj, form, force): - PathLog.track(obj.Label, force) + Path.Log.track(obj.Label, force) self.obj = obj self.form = form self.force = force @@ -304,7 +301,7 @@ class StockEdit(object): return PathStock.StockType.FromStock(obj.Stock) == cls.StockType def activate(self, obj, select=False): - PathLog.track(obj.Label, select) + Path.Log.track(obj.Label, select) def showHide(widget, activeWidget): if widget == activeWidget: @@ -322,11 +319,11 @@ class StockEdit(object): self.setFields(obj) def setStock(self, obj, stock): - PathLog.track(obj.Label, stock) + Path.Log.track(obj.Label, stock) if obj.Stock: - PathLog.track(obj.Stock.Name) + Path.Log.track(obj.Stock.Name) obj.Document.removeObject(obj.Stock.Name) - PathLog.track(stock.Name) + Path.Log.track(stock.Name) obj.Stock = stock if stock.ViewObject and stock.ViewObject.Proxy: stock.ViewObject.Proxy.onEdit(_OpenCloseResourceEditor) @@ -359,7 +356,7 @@ class StockFromBaseBoundBoxEdit(StockEdit): self.trackZpos = None def editorFrame(self): - PathLog.track() + Path.Log.track() return self.form.stockFromBase def getFieldsStock(self, stock, fields=None): @@ -384,16 +381,16 @@ class StockFromBaseBoundBoxEdit(StockEdit): def getFields(self, obj, fields=None): if fields is None: fields = ["xneg", "xpos", "yneg", "ypos", "zneg", "zpos"] - PathLog.track(obj.Label, fields) + Path.Log.track(obj.Label, fields) if self.IsStock(obj): self.getFieldsStock(obj.Stock, fields) else: - PathLog.error("Stock not from Base bound box!") + Path.Log.error("Stock not from Base bound box!") def setFields(self, obj): - PathLog.track() + Path.Log.track() if self.force or not self.IsStock(obj): - PathLog.track() + Path.Log.track() stock = PathStock.CreateFromBase(obj) if self.force and self.editorFrame().isVisible(): self.getFieldsStock(stock) @@ -407,7 +404,7 @@ class StockFromBaseBoundBoxEdit(StockEdit): self.setLengthField(self.form.stockExtZpos, obj.Stock.ExtZpos) def setupUi(self, obj): - PathLog.track() + Path.Log.track() self.setFields(obj) self.checkXpos() self.checkYpos() @@ -480,7 +477,7 @@ class StockCreateBoxEdit(StockEdit): self.form.stockBoxHeight.text() ) else: - PathLog.error("Stock not a box!") + Path.Log.error("Stock not a box!") except Exception: pass @@ -526,7 +523,7 @@ class StockCreateCylinderEdit(StockEdit): self.form.stockCylinderHeight.text() ) else: - PathLog.error(translate("Path_Job", "Stock not a cylinder!")) + Path.Log.error(translate("Path_Job", "Stock not a cylinder!")) except Exception: pass @@ -637,7 +634,7 @@ class TaskPanel: self.form.toolControllerList.resizeColumnsToContents() currentPostProcessor = self.obj.PostProcessor - postProcessors = PathPreferences.allEnabledPostProcessors( + postProcessors = Path.Preferences.allEnabledPostProcessors( ["", currentPostProcessor] ) for post in postProcessors: @@ -687,13 +684,13 @@ class TaskPanel: box.addItem(text, data) def preCleanup(self): - PathLog.track() + Path.Log.track() FreeCADGui.Selection.removeObserver(self) self.vproxy.resetEditVisibility(self.obj) self.vproxy.resetTaskPanel() def accept(self, resetEdit=True): - PathLog.track() + Path.Log.track() self._jobIntegrityCheck() # Check existence of Model and Tools self.preCleanup() self.getFields() @@ -703,19 +700,19 @@ class TaskPanel: self.cleanup(resetEdit) def reject(self, resetEdit=True): - PathLog.track() + Path.Log.track() self.preCleanup() self.setupGlobal.reject() self.setupOps.reject() FreeCAD.ActiveDocument.abortTransaction() if self.deleteOnReject and FreeCAD.ActiveDocument.getObject(self.name): - PathLog.info("Uncreate Job") + Path.Log.info("Uncreate Job") FreeCAD.ActiveDocument.openTransaction("Uncreate Job") if self.obj.ViewObject.Proxy.onDelete(self.obj.ViewObject, None): FreeCAD.ActiveDocument.removeObject(self.obj.Name) FreeCAD.ActiveDocument.commitTransaction() else: - PathLog.track( + Path.Log.track( self.name, self.deleteOnReject, FreeCAD.ActiveDocument.getObject(self.name), @@ -724,7 +721,7 @@ class TaskPanel: return True def cleanup(self, resetEdit): - PathLog.track() + Path.Log.track() FreeCADGui.Control.closeDialog() if resetEdit: FreeCADGui.ActiveDocument.resetEdit() @@ -779,7 +776,7 @@ class TaskPanel: flist.append(self.form.wcslist.item(i).text()) self.obj.Fixtures = flist except Exception as e: - PathLog.debug(e) + Path.Log.debug(e) FreeCAD.Console.PrintWarning( "The Job was created without fixture support. Please delete and recreate the job\r\n" ) @@ -999,35 +996,30 @@ class TaskPanel: # Try to find a tool number from the currently selected lib. Otherwise # use next available number - if PathPreferences.toolsUseLegacyTools(): - PathToolLibraryEditor.CommandToolLibraryEdit().edit( - self.obj, self.updateToolController + tools = PathToolBitGui.LoadTools() + + curLib = Path.Preferences.lastFileToolLibrary() + + library = None + if curLib is not None: + with open(curLib) as fp: + library = json.load(fp) + + for tool in tools: + toolNum = self.obj.Proxy.nextToolNumber() + if library is not None: + for toolBit in library["tools"]: + + if toolBit["path"] == tool.File: + toolNum = toolBit["nr"] + + tc = PathToolControllerGui.Create( + name=tool.Label, tool=tool, toolNumber=toolNum ) - else: - tools = PathToolBitGui.LoadTools() + self.obj.Proxy.addToolController(tc) - curLib = PathPreferences.lastFileToolLibrary() - - library = None - if curLib is not None: - with open(curLib) as fp: - library = json.load(fp) - - for tool in tools: - toolNum = self.obj.Proxy.nextToolNumber() - if library is not None: - for toolBit in library["tools"]: - - if toolBit["path"] == tool.File: - toolNum = toolBit["nr"] - - tc = PathToolControllerGui.Create( - name=tool.Label, tool=tool, toolNumber=toolNum - ) - self.obj.Proxy.addToolController(tc) - - FreeCAD.ActiveDocument.recompute() - self.updateToolController() + FreeCAD.ActiveDocument.recompute() + self.updateToolController() def toolControllerDelete(self): self.objectDelete(self.form.toolControllerList) @@ -1083,17 +1075,17 @@ class TaskPanel: self.template.updateUI() def modelSetAxis(self, axis): - PathLog.track(axis) + Path.Log.track(axis) def alignSel(sel, normal, flip=False): - PathLog.track( + Path.Log.track( "Vector(%.2f, %.2f, %.2f)" % (normal.x, normal.y, normal.z), flip ) v = axis if flip: v = axis.negative() - if PathGeom.pointsCoincide(abs(v), abs(normal)): + if Path.Geom.pointsCoincide(abs(v), abs(normal)): # Selection is already aligned with the axis of rotation leading # to a (0,0,0) cross product for rotation. # --> Need to flip the object around one of the "other" axis. @@ -1104,7 +1096,7 @@ class TaskPanel: else: r = v.cross(normal) # rotation axis a = DraftVecUtils.angle(normal, v, r) * 180 / math.pi - PathLog.debug( + Path.Log.debug( "oh boy: (%.2f, %.2f, %.2f) x (%.2f, %.2f, %.2f) -> (%.2f, %.2f, %.2f) -> %.2f" % (v.x, v.y, v.z, normal.x, normal.y, normal.z, r.x, r.y, r.z, a) ) @@ -1117,26 +1109,26 @@ class TaskPanel: selObject = sel.Object for feature in sel.SubElementNames: selFeature = feature - PathLog.track(selObject.Label, feature) + Path.Log.track(selObject.Label, feature) sub = sel.Object.Shape.getElement(feature) if "Face" == sub.ShapeType: normal = sub.normalAt(0, 0) if sub.Orientation == "Reversed": normal = FreeCAD.Vector() - normal - PathLog.debug( + Path.Log.debug( "(%.2f, %.2f, %.2f) -> reversed (%s)" % (normal.x, normal.y, normal.z, sub.Orientation) ) else: - PathLog.debug( + Path.Log.debug( "(%.2f, %.2f, %.2f) -> forward (%s)" % (normal.x, normal.y, normal.z, sub.Orientation) ) - if PathGeom.pointsCoincide(axis, normal): + if Path.Geom.pointsCoincide(axis, normal): alignSel(sel, normal, True) - elif PathGeom.pointsCoincide(axis, FreeCAD.Vector() - normal): + elif Path.Geom.pointsCoincide(axis, FreeCAD.Vector() - normal): alignSel(sel, FreeCAD.Vector() - normal, True) else: alignSel(sel, normal) @@ -1145,9 +1137,9 @@ class TaskPanel: normal = ( sub.Vertexes[1].Point - sub.Vertexes[0].Point ).normalize() - if PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide( axis, normal - ) or PathGeom.pointsCoincide(axis, FreeCAD.Vector() - normal): + ) or Path.Geom.pointsCoincide(axis, FreeCAD.Vector() - normal): # Don't really know the orientation of an edge, so let's just flip the object # and if the user doesn't like it they can flip again alignSel(sel, normal, True) @@ -1155,7 +1147,7 @@ class TaskPanel: alignSel(sel, normal) else: - PathLog.track(sub.ShapeType) + Path.Log.track(sub.ShapeType) if selObject and selFeature: FreeCADGui.Selection.clearSelection() @@ -1167,19 +1159,19 @@ class TaskPanel: FreeCADGui.Selection.addSelection(sel.Object, sel.SubElementNames) def modelSet0(self, axis): - PathLog.track(axis) + Path.Log.track(axis) with selectionEx() as selection: for sel in selection: selObject = sel.Object - PathLog.track(selObject.Label) + Path.Log.track(selObject.Label) for name in sel.SubElementNames: - PathLog.track(selObject.Label, name) + Path.Log.track(selObject.Label, name) feature = selObject.Shape.getElement(name) bb = feature.BoundBox offset = FreeCAD.Vector( axis.x * bb.XMax, axis.y * bb.YMax, axis.z * bb.ZMax ) - PathLog.track(feature.BoundBox.ZMax, offset) + Path.Log.track(feature.BoundBox.ZMax, offset) p = selObject.Placement p.move(offset) selObject.Placement = p @@ -1254,7 +1246,7 @@ class TaskPanel: def updateStockEditor(self, index, force=False): def setupFromBaseEdit(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockFromBase: self.stockFromBase = StockFromBaseBoundBoxEdit( self.obj, self.form, force @@ -1262,13 +1254,13 @@ class TaskPanel: self.stockEdit = self.stockFromBase def setupCreateBoxEdit(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockCreateBox: self.stockCreateBox = StockCreateBoxEdit(self.obj, self.form, force) self.stockEdit = self.stockCreateBox def setupCreateCylinderEdit(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockCreateCylinder: self.stockCreateCylinder = StockCreateCylinderEdit( self.obj, self.form, force @@ -1276,7 +1268,7 @@ class TaskPanel: self.stockEdit = self.stockCreateCylinder def setupFromExisting(): - PathLog.track(index, force) + Path.Log.track(index, force) if force or not self.stockFromExisting: self.stockFromExisting = StockFromExistingEdit( self.obj, self.form, force @@ -1296,7 +1288,7 @@ class TaskPanel: elif StockFromExistingEdit.IsStock(self.obj): setupFromExisting() else: - PathLog.error( + Path.Log.error( translate("Path_Job", "Unsupported stock object %s") % self.obj.Stock.Label ) @@ -1312,7 +1304,7 @@ class TaskPanel: setupFromBaseEdit() index = -1 else: - PathLog.error( + Path.Log.error( translate("Path_Job", "Unsupported stock type %s (%d)") % (self.form.stock.currentText(), index) ) @@ -1443,7 +1435,7 @@ class TaskPanel: if obsolete or additions: self.setFields() else: - PathLog.track("no changes to model") + Path.Log.track("no changes to model") def tabPageChanged(self, index): if index == 0: @@ -1459,7 +1451,7 @@ class TaskPanel: try: self.setupOps.setupUi() except Exception as ee: - PathLog.error(str(ee)) + Path.Log.error(str(ee)) self.updateStockEditor(-1, False) self.setFields() @@ -1635,7 +1627,7 @@ class TaskPanel: def Create(base, template=None, openTaskPanel=True): """Create(base, template) ... creates a job instance for the given base object using template to configure it.""" - FreeCADGui.addModule("PathScripts.PathJob") + FreeCADGui.addModule("Path.Main.Job") FreeCAD.ActiveDocument.openTransaction("Create Job") try: obj = PathJob.Create("Job", base, template) @@ -1649,7 +1641,7 @@ def Create(base, template=None, openTaskPanel=True): obj.ViewObject.Proxy.deleteOnReject = False return obj except Exception as exc: - PathLog.error(exc) + Path.Log.error(exc) traceback.print_exc() FreeCAD.ActiveDocument.abortTransaction() diff --git a/src/Mod/Path/PathScripts/PathJobCmd.py b/src/Mod/Path/Path/Main/Gui/JobCmd.py similarity index 92% rename from src/Mod/Path/PathScripts/PathJobCmd.py rename to src/Mod/Path/Path/Main/Gui/JobCmd.py index 830eb23aef..33ca911867 100644 --- a/src/Mod/Path/PathScripts/PathJobCmd.py +++ b/src/Mod/Path/Path/Main/Gui/JobCmd.py @@ -24,12 +24,11 @@ from PySide import QtCore, QtGui from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import FreeCADGui -import PathScripts.PathJob as PathJob -import PathScripts.PathJobDlg as PathJobDlg -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathStock as PathStock -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Util as PathUtil +import Path.Main.Gui.JobDlg as PathJobDlg +import Path.Main.Job as PathJob +import Path.Main.Stock as PathStock import json import os @@ -37,10 +36,10 @@ import os translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class CommandJobCreate: @@ -76,13 +75,13 @@ class CommandJobCreate: @classmethod def Execute(cls, base, template): - FreeCADGui.addModule("PathScripts.PathJobGui") + FreeCADGui.addModule("Path.Main.Gui.Job") if template: template = "'%s'" % template else: template = "None" FreeCADGui.doCommand( - "PathScripts.PathJobGui.Create(%s, %s)" % ([o.Name for o in base], template) + "Path.Main.Gui.Job.Create(%s, %s)" % ([o.Name for o in base], template) ) @@ -136,7 +135,7 @@ class CommandJobTemplateExport: foo = QtGui.QFileDialog.getSaveFileName( QtGui.QApplication.activeWindow(), "Path - Job Template", - PathPreferences.filePath(), + Path.Preferences.filePath(), "job_*.json", )[0] if foo: diff --git a/src/Mod/Path/PathScripts/PathJobDlg.py b/src/Mod/Path/Path/Main/Gui/JobDlg.py similarity index 96% rename from src/Mod/Path/PathScripts/PathJobDlg.py rename to src/Mod/Path/Path/Main/Gui/JobDlg.py index d0acdfda70..4476dc0a00 100644 --- a/src/Mod/Path/PathScripts/PathJobDlg.py +++ b/src/Mod/Path/Path/Main/Gui/JobDlg.py @@ -24,11 +24,10 @@ from PySide import QtCore, QtGui from collections import Counter import FreeCAD import FreeCADGui -import PathScripts.PathJob as PathJob -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathStock as PathStock -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Util as PathUtil +import Path.Main.Job as PathJob +import Path.Main.Stock as PathStock import glob import os @@ -36,10 +35,10 @@ translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class _ItemDelegate(QtGui.QStyledItemDelegate): @@ -223,7 +222,7 @@ class JobCreate: def setupTemplate(self): templateFiles = [] - for path in PathPreferences.searchPaths(): + for path in Path.Preferences.searchPaths(): cleanPaths = [ f.replace("\\", "/") for f in self.templateFilesIn(path) ] # Standardize slashes used across os platforms @@ -238,9 +237,9 @@ class JobCreate: while name in template: i = i + 1 name = basename + " (%s)" % i - PathLog.track(name, tFile) + Path.Log.track(name, tFile) template[name] = tFile - selectTemplate = PathPreferences.defaultJobTemplate() + selectTemplate = Path.Preferences.defaultJobTemplate() index = 0 self.dialog.jobTemplate.addItem("", "") for name in sorted(template.keys()): @@ -253,7 +252,7 @@ class JobCreate: def templateFilesIn(self, path): """templateFilesIn(path) ... answer all file in the given directory which fit the job template naming convention. PathJob template files are name job_*.json""" - PathLog.track(path) + Path.Log.track(path) return glob.glob(path + "/job_*.json") def getModels(self): @@ -353,7 +352,7 @@ class JobTemplateExport: else: # Existing Solid seHint = "-" - PathLog.error(translate("Path_Job", "Unsupported stock type")) + Path.Log.error(translate("Path_Job", "Unsupported stock type")) self.dialog.stockExtentHint.setText(seHint) spHint = "%s" % job.Stock.Placement self.dialog.stockPlacementHint.setText(spHint) diff --git a/src/Mod/Path/PathScripts/PathPreferencesPathJob.py b/src/Mod/Path/Path/Main/Gui/PreferencesJob.py similarity index 90% rename from src/Mod/Path/PathScripts/PathPreferencesPathJob.py rename to src/Mod/Path/Path/Main/Gui/PreferencesJob.py index 3164438998..7d3d3c0b8a 100644 --- a/src/Mod/Path/PathScripts/PathPreferencesPathJob.py +++ b/src/Mod/Path/Path/Main/Gui/PreferencesJob.py @@ -22,17 +22,15 @@ import FreeCAD import Path -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathStock as PathStock +import Path.Main.Stock as PathStock +import Path.Post.Processor as PostProcessor import json from FreeCAD import Units from PySide import QtCore, QtGui -from PathScripts.PathPostProcessor import PostProcessor -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class JobPreferencesPage: @@ -53,7 +51,7 @@ class JobPreferencesPage: jobTemplate = self.form.leDefaultJobTemplate.text() geometryTolerance = Units.Quantity(self.form.geometryTolerance.text()) curveAccuracy = Units.Quantity(self.form.curveAccuracy.text()) - PathPreferences.setJobDefaults( + Path.Preferences.setJobDefaults( filePath, jobTemplate, geometryTolerance, curveAccuracy ) @@ -67,11 +65,11 @@ class JobPreferencesPage: item = self.form.postProcessorList.item(i) if item.checkState() == QtCore.Qt.CheckState.Unchecked: blacklist.append(item.text()) - PathPreferences.setPostProcessorDefaults(processor, args, blacklist) + Path.Preferences.setPostProcessorDefaults(processor, args, blacklist) path = str(self.form.leOutputFile.text()) policy = str(self.form.cboOutputPolicy.currentText()) - PathPreferences.setOutputFileDefaults(path, policy) + Path.Preferences.setOutputFileDefaults(path, policy) self.saveStockSettings() self.saveToolsSettings() @@ -142,14 +140,13 @@ class JobPreferencesPage: attrs["posZ"] = FreeCAD.Units.Quantity( self.form.stockPositionZ.text() ).Value - PathPreferences.setDefaultStockTemplate(json.dumps(attrs)) + Path.Preferences.setDefaultStockTemplate(json.dumps(attrs)) else: - PathPreferences.setDefaultStockTemplate("") + Path.Preferences.setDefaultStockTemplate("") def saveToolsSettings(self): - PathPreferences.setToolsSettings( - self.form.toolsUseLegacy.isChecked(), - self.form.toolsAbsolutePaths.isChecked(), + Path.Preferences.setToolsSettings( + self.form.toolsAbsolutePaths.isChecked() ) def selectComboEntry(self, widget, text): @@ -183,11 +180,11 @@ class JobPreferencesPage: ) def loadSettings(self): - self.form.leDefaultFilePath.setText(PathPreferences.defaultFilePath()) - self.form.leDefaultJobTemplate.setText(PathPreferences.defaultJobTemplate()) + self.form.leDefaultFilePath.setText(Path.Preferences.defaultFilePath()) + self.form.leDefaultJobTemplate.setText(Path.Preferences.defaultJobTemplate()) - blacklist = PathPreferences.postProcessorBlacklist() - for processor in PathPreferences.allAvailablePostProcessors(): + blacklist = Path.Preferences.postProcessorBlacklist() + for processor in Path.Preferences.allAvailablePostProcessors(): item = QtGui.QListWidgetItem(processor) if processor in blacklist: item.setCheckState(QtCore.Qt.CheckState.Unchecked) @@ -200,26 +197,26 @@ class JobPreferencesPage: ) self.form.postProcessorList.addItem(item) self.verifyAndUpdateDefaultPostProcessorWith( - PathPreferences.defaultPostProcessor() + Path.Preferences.defaultPostProcessor() ) self.form.defaultPostProcessorArgs.setText( - PathPreferences.defaultPostProcessorArgs() + Path.Preferences.defaultPostProcessorArgs() ) geomTol = Units.Quantity( - PathPreferences.defaultGeometryTolerance(), Units.Length + Path.Preferences.defaultGeometryTolerance(), Units.Length ) self.form.geometryTolerance.setText(geomTol.UserString) self.form.curveAccuracy.setText( Units.Quantity( - PathPreferences.defaultLibAreaCurveAccuracy(), Units.Length + Path.Preferences.defaultLibAreaCurveAccuracy(), Units.Length ).UserString ) - self.form.leOutputFile.setText(PathPreferences.defaultOutputFile()) + self.form.leOutputFile.setText(Path.Preferences.defaultOutputFile()) self.selectComboEntry( - self.form.cboOutputPolicy, PathPreferences.defaultOutputPolicy() + self.form.cboOutputPolicy, Path.Preferences.defaultOutputPolicy() ) self.form.tbDefaultFilePath.clicked.connect(self.browseDefaultFilePath) @@ -237,7 +234,7 @@ class JobPreferencesPage: self.loadToolSettings() def loadStockSettings(self): - stock = PathPreferences.defaultStockTemplate() + stock = Path.Preferences.defaultStockTemplate() index = -1 if stock: attrs = json.loads(stock) @@ -329,9 +326,8 @@ class JobPreferencesPage: self.form.stockCreateCylinder.hide() def loadToolSettings(self): - self.form.toolsUseLegacy.setChecked(PathPreferences.toolsUseLegacyTools()) self.form.toolsAbsolutePaths.setChecked( - PathPreferences.toolsStoreAbsolutePaths() + Path.Preferences.toolsStoreAbsolutePaths() ) def getPostProcessor(self, name): @@ -373,7 +369,7 @@ class JobPreferencesPage: def bestGuessForFilePath(self): path = self.form.leDefaultFilePath.text() if not path: - path = PathPreferences.filePath() + path = Path.Preferences.filePath() return path def browseDefaultJobTemplate(self): diff --git a/src/Mod/Path/PathScripts/PathSanity.py b/src/Mod/Path/Path/Main/Gui/Sanity.py similarity index 97% rename from src/Mod/Path/PathScripts/PathSanity.py rename to src/Mod/Path/Path/Main/Gui/Sanity.py index b7478ea422..0ba6da50e4 100644 --- a/src/Mod/Path/PathScripts/PathSanity.py +++ b/src/Mod/Path/Path/Main/Gui/Sanity.py @@ -32,10 +32,9 @@ from __future__ import print_function from PySide import QtCore, QtGui import FreeCAD import FreeCADGui +import Path +import Path.Base.Util as PathUtil import PathScripts -import PathScripts.PathLog as PathLog -import PathScripts.PathUtil as PathUtil -import PathScripts.PathPreferences as PathPreferences from collections import Counter from datetime import datetime import os @@ -47,18 +46,18 @@ translate = FreeCAD.Qt.translate LOG_MODULE = "PathSanity" -# PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) -# PathLog.trackModule('PathSanity') +# Path.Log.setLevel(Path.Log.Level.INFO, LOG_MODULE) +# Path.Log.trackModule('PathSanity') class CommandPathSanity: def resolveOutputPath(self, job): if job.PostProcessorOutputFile != "": filepath = job.PostProcessorOutputFile - elif PathPreferences.defaultOutputFile() != "": - filepath = PathPreferences.defaultOutputFile() + elif Path.Preferences.defaultOutputFile() != "": + filepath = Path.Preferences.defaultOutputFile() else: - filepath = PathPreferences.macroFilePath() + filepath = Path.Preferences.macroFilePath() if "%D" in filepath: D = FreeCAD.ActiveDocument.FileName @@ -87,14 +86,14 @@ class CommandPathSanity: M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir()) filepath = filepath.replace("%M", M) - PathLog.debug("filepath: {}".format(filepath)) + Path.Log.debug("filepath: {}".format(filepath)) # starting at the derived filename, iterate up until we have a valid # directory to write to while not os.path.isdir(filepath): filepath = os.path.dirname(filepath) - PathLog.debug("filepath: {}".format(filepath)) + Path.Log.debug("filepath: {}".format(filepath)) return filepath + os.sep def GetResources(self): @@ -111,7 +110,7 @@ class CommandPathSanity: def IsActive(self): obj = FreeCADGui.Selection.getSelectionEx()[0].Object - return isinstance(obj.Proxy, PathScripts.PathJob.ObjectJob) + return isinstance(obj.Proxy, Path.Main.Job.ObjectJob) def Activated(self): # if everything is ok, execute @@ -552,7 +551,7 @@ class CommandPathSanity: m = 0 for i in obj.Document.Objects: if hasattr(i, "Proxy"): - if isinstance(i.Proxy, PathScripts.PathJob.ObjectJob): + if isinstance(i.Proxy, Path.Main.Job.ObjectJob): m += 1 if i is obj: n = m @@ -820,7 +819,7 @@ class CommandPathSanity: fname = obj.PostProcessorOutputFile data["outputfilename"] = os.path.splitext(os.path.basename(fname))[0] for op in obj.Operations.Group: - if isinstance(op.Proxy, PathScripts.PathStop.Stop) and op.Stop is True: + if isinstance(op.Proxy, Path.Op.Gui.Stop.Stop) and op.Stop is True: data["optionalstops"] = "True" if obj.LastPostProcessOutput == "": diff --git a/src/Mod/Path/PathScripts/PathSimulatorGui.py b/src/Mod/Path/Path/Main/Gui/Simulator.py similarity index 95% rename from src/Mod/Path/PathScripts/PathSimulatorGui.py rename to src/Mod/Path/Path/Main/Gui/Simulator.py index ba712b6092..430f12b559 100644 --- a/src/Mod/Path/PathScripts/PathSimulatorGui.py +++ b/src/Mod/Path/Path/Main/Gui/Simulator.py @@ -22,12 +22,10 @@ import FreeCAD import Path -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathDressup as PathDressup -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathUtil as PathUtil -import PathScripts.PathJob as PathJob +import Path.Base.Util as PathUtil +import Path.Dressup.Utils as PathDressup +import Path.Main.Job as PathJob +import PathGui import PathSimulator import math import os @@ -189,20 +187,7 @@ class PathSimulation: self.tool = None if self.tool is not None: - if isinstance(self.tool, Path.Tool): - # handle legacy tools - toolProf = self.CreateToolProfile( - self.tool, - Vector(0, 1, 0), - Vector(0, 0, 0), - float(self.tool.Diameter) / 2.0, - ) - self.cutTool.Shape = Part.makeSolid( - toolProf.revolve(Vector(0, 0, 0), Vector(0, 0, 1)) - ) - else: - # handle tool bits - self.cutTool.Shape = self.tool.Shape + self.cutTool.Shape = self.tool.Shape if not self.cutTool.Shape.isValid() or self.cutTool.Shape.isNull(): self.EndSimulation() @@ -413,14 +398,14 @@ class PathSimulation: self.PerformCutBoolean() def RapidMove(self, cmd, curpos): - path = PathGeom.edgeForCmd(cmd, curpos) # hack to overcome occ bug + path = Path.Geom.edgeForCmd(cmd, curpos) # hack to overcome occ bug if path is None: return curpos return path.valueAt(path.LastParameter) # get a solid representation of a tool going along path def GetPathSolid(self, tool, cmd, pos): - toolPath = PathGeom.edgeForCmd(cmd, pos) + toolPath = Path.Geom.edgeForCmd(cmd, pos) startDir = toolPath.tangentAt(0) startDir[2] = 0.0 endPos = toolPath.valueAt(toolPath.LastParameter) @@ -475,7 +460,7 @@ class PathSimulation: h = tool.CuttingEdgeHeight if h <= 0.0: # set default if user fails to avoid freeze h = 1.0 - PathLog.error("SET Tool Length") + Path.Log.error("SET Tool Length") # common to all tools vTR = Vector(xp + yf, yp - xf, zp + h) vTC = Vector(xp, yp, zp + h) diff --git a/src/Mod/Path/Path/Main/Gui/__init__.py b/src/Mod/Path/Path/Main/Gui/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/Path/Main/Job.py similarity index 93% rename from src/Mod/Path/PathScripts/PathJob.py rename to src/Mod/Path/Path/Main/Job.py index d2b64c1405..23203f4b21 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/Path/Main/Job.py @@ -20,19 +20,17 @@ # * * # *************************************************************************** -from PathScripts.PathPostProcessor import PostProcessor +from Path.Post.Processor import PostProcessor from PySide import QtCore from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathSetupSheet as PathSetupSheet -import PathScripts.PathStock as PathStock -import PathScripts.PathToolController as PathToolController -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.SetupSheet as PathSetupSheet +import Path.Base.Util as PathUtil +import Path.Main.Stock as PathStock +import Path.Tool.Controller as PathToolController import json import time -import Path # lazily loaded modules @@ -42,10 +40,10 @@ Draft = LazyLoader("Draft", globals(), "Draft") if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -83,9 +81,9 @@ def createResourceClone(obj, orig, name, icon): clone.addProperty("App::PropertyString", "PathResource") clone.PathResource = name if clone.ViewObject: - import PathScripts.PathIconViewProvider + import Path.Base.Gui.IconViewProvider - PathScripts.PathIconViewProvider.Attach(clone.ViewObject, icon) + Path.Base.Gui.IconViewProvider.Attach(clone.ViewObject, icon) clone.ViewObject.Visibility = False clone.ViewObject.Transparency = 80 obj.Document.recompute() # necessary to create the clone shape @@ -223,16 +221,16 @@ class ObjectJob: for n in self.propertyEnumerations(): setattr(obj, n[0], n[1]) - obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile() - obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors() - defaultPostProcessor = PathPreferences.defaultPostProcessor() + obj.PostProcessorOutputFile = Path.Preferences.defaultOutputFile() + obj.PostProcessor = postProcessors = Path.Preferences.allEnabledPostProcessors() + defaultPostProcessor = Path.Preferences.defaultPostProcessor() # Check to see if default post processor hasn't been 'lost' (This can happen when Macro dir has changed) if defaultPostProcessor in postProcessors: obj.PostProcessor = defaultPostProcessor else: obj.PostProcessor = postProcessors[0] - obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs() - obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance() + obj.PostProcessorArgs = Path.Preferences.defaultPostProcessorArgs() + obj.GeometryTolerance = Path.Preferences.defaultGeometryTolerance() self.setupOperations(obj) self.setupSetupSheet(obj) @@ -272,11 +270,11 @@ class ObjectJob: data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -307,16 +305,16 @@ class ObjectJob: ) obj.SetupSheet = PathSetupSheet.Create() if obj.SetupSheet.ViewObject: - import PathScripts.PathIconViewProvider + import Path.Base.Gui.IconViewProvider - PathScripts.PathIconViewProvider.Attach( + Path.Base.Gui.IconViewProvider.Attach( obj.SetupSheet.ViewObject, "SetupSheet" ) obj.SetupSheet.Label = "SetupSheet" self.setupSheet = obj.SetupSheet.Proxy def setupBaseModel(self, obj, models=None): - PathLog.track(obj.Label, models) + Path.Log.track(obj.Label, models) addModels = False if not hasattr(obj, "Model"): @@ -346,7 +344,7 @@ class ObjectJob: obj.Model.Label = "Model" if hasattr(obj, "Base"): - PathLog.info( + Path.Log.info( "Converting Job.Base to new Job.Model for {}".format(obj.Label) ) obj.Model.addObject(obj.Base) @@ -383,7 +381,7 @@ class ObjectJob: def setupStock(self, obj): """setupStock(obj)... setup the Stock for the Job object.""" if not obj.Stock: - stockTemplate = PathPreferences.defaultStockTemplate() + stockTemplate = Path.Preferences.defaultStockTemplate() if stockTemplate: obj.Stock = PathStock.CreateFromTemplate(obj, json.loads(stockTemplate)) if not obj.Stock: @@ -403,12 +401,12 @@ class ObjectJob: def onDelete(self, obj, arg2=None): """Called by the view provider, there doesn't seem to be a callback on the obj itself.""" - PathLog.track(obj.Label, arg2) + Path.Log.track(obj.Label, arg2) doc = obj.Document if getattr(obj, "Operations", None): # the first to tear down are the ops, they depend on other resources - PathLog.debug( + Path.Log.debug( "taking down ops: %s" % [o.Name for o in self.allOperations()] ) while obj.Operations.Group: @@ -426,7 +424,7 @@ class ObjectJob: # stock could depend on Model, so delete it first if getattr(obj, "Stock", None): - PathLog.debug("taking down stock") + Path.Log.debug("taking down stock") PathUtil.clearExpressionEngine(obj.Stock) doc.removeObject(obj.Stock.Name) obj.Stock = None @@ -434,7 +432,7 @@ class ObjectJob: # base doesn't depend on anything inside job if getattr(obj, "Model", None): for base in obj.Model.Group: - PathLog.debug("taking down base %s" % base.Label) + Path.Log.debug("taking down base %s" % base.Label) self.removeBase(obj, base, False) obj.Model.Group = [] doc.removeObject(obj.Model.Name) @@ -442,7 +440,7 @@ class ObjectJob: # Tool controllers might refer to either legacy tool or toolbit if getattr(obj, "Tools", None): - PathLog.debug("taking down tool controller") + Path.Log.debug("taking down tool controller") for tc in obj.Tools.Group: if hasattr(tc.Tool, "Proxy"): PathUtil.clearExpressionEngine(tc.Tool) @@ -549,14 +547,6 @@ class ObjectJob: for n in self.propertyEnumerations(): setattr(obj, n[0], n[1]) - if True in [isinstance(t.Tool, Path.Tool) for t in obj.Tools.Group]: - FreeCAD.Console.PrintWarning( - translate( - "Path", - "This job contains Legacy tools. Legacy tools are deprecated. They will be removed after version 0.20", - ) - ) - def onChanged(self, obj, prop): if prop == "PostProcessor" and obj.PostProcessor: processor = PostProcessor.load(obj.PostProcessor) @@ -614,7 +604,11 @@ class ObjectJob: if attrs.get(JobTemplate.ToolController): for tc in attrs.get(JobTemplate.ToolController): - tcs.append(PathToolController.FromTemplate(tc)) + ctrl = PathToolController.FromTemplate(tc) + if ctrl: + tcs.append(ctrl) + else: + Path.Log.debug(f"skipping TC {tc['name']}") if attrs.get(JobTemplate.Stock): obj.Stock = PathStock.CreateFromTemplate( obj, attrs.get(JobTemplate.Stock) @@ -631,10 +625,11 @@ class ObjectJob: if attrs.get(JobTemplate.SplitOutput): obj.SplitOutput = attrs.get(JobTemplate.SplitOutput) - PathLog.debug("setting tool controllers (%d)" % len(tcs)) - obj.Tools.Group = tcs + Path.Log.debug("setting tool controllers (%d)" % len(tcs)) + if tcs: + obj.Tools.Group = tcs else: - PathLog.error( + Path.Log.error( "Unsupported PathJob template version {}".format( attrs.get(JobTemplate.Version) ) @@ -719,7 +714,7 @@ class ObjectJob: if removeBefore: group.remove(before) except Exception as e: - PathLog.error(e) + Path.Log.error(e) group.append(op) else: group.append(op) @@ -736,7 +731,7 @@ class ObjectJob: def addToolController(self, tc): group = self.obj.Tools.Group - PathLog.debug( + Path.Log.debug( "addToolController(%s): %s" % (tc.Label, [t.Label for t in group]) ) if tc.Name not in [str(t.Name) for t in group]: @@ -795,7 +790,7 @@ class ObjectJob: suffix = job.Name[3:] def errorMessage(grp, job): - PathLog.error("{} corrupt in {} job.".format(grp, job.Name)) + Path.Log.error("{} corrupt in {} job.".format(grp, job.Name)) if not job.Operations: self.setupOperations(job) diff --git a/src/Mod/Path/PathScripts/PathStock.py b/src/Mod/Path/Path/Main/Stock.py similarity index 93% rename from src/Mod/Path/PathScripts/PathStock.py rename to src/Mod/Path/Path/Main/Stock.py index 2338061477..f467da5011 100644 --- a/src/Mod/Path/PathScripts/PathStock.py +++ b/src/Mod/Path/Path/Main/Stock.py @@ -23,7 +23,7 @@ """Used to create material stock around a machined part - for visualization""" import FreeCAD -import PathScripts.PathLog as PathLog +import Path import math from PySide.QtCore import QT_TRANSLATE_NOOP from PySide import QtCore @@ -36,10 +36,10 @@ Part = LazyLoader("Part", globals(), "Part") translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class StockType: @@ -69,7 +69,7 @@ class StockType: def shapeBoundBox(obj): - PathLog.track(type(obj)) + Path.Log.track(type(obj)) if list == type(obj) and obj: bb = FreeCAD.BoundBox() for o in obj: @@ -86,7 +86,7 @@ def shapeBoundBox(obj): bb = bb.united(b) return bb if obj: - PathLog.error( + Path.Log.error( translate("PathStock", "Invalid base object %s - no shape found") % obj.Name ) return None @@ -185,7 +185,7 @@ class StockFromBase(Stock): FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin), FreeCAD.Rotation() ) else: - PathLog.track(obj.Label, base.Label) + Path.Log.track(obj.Label, base.Label) obj.Proxy = self # debugging aids @@ -206,7 +206,7 @@ class StockFromBase(Stock): if obj.Base and hasattr(obj.Base, "Group") else None ) - PathLog.track(obj.Label, bb) + Path.Log.track(obj.Label, bb) # Sometimes, when the Base changes it's temporarily not assigned when # Stock.execute is triggered - it'll be set correctly the next time around. @@ -325,9 +325,8 @@ class StockCreateCylinder(Stock): if prop in ["Radius", "Height"] and not "Restore" in obj.State: self.execute(obj) - def SetupStockObject(obj, stockType): - PathLog.track(obj.Label, stockType) + Path.Log.track(obj.Label, stockType) if FreeCAD.GuiUp and obj.ViewObject: obj.addProperty( "App::PropertyString", @@ -338,9 +337,15 @@ def SetupStockObject(obj, stockType): obj.StockType = stockType obj.setEditorMode("StockType", 2) # hide - import PathScripts.PathIconViewProvider + # If I don't rename the module then usage as Path.Base.Gui.IconViewProvider below + # 'causes above Path.Log.track(...) to fail with - claiming that Path is accessed + # before it's assigned. + # Alternative _another_ `import Path` statement in front of `Path.Log.track(...)` + # also prevents the issue from happening. + # Go figure. + import Path.Base.Gui.IconViewProvider as PathIconViewProvider - PathScripts.PathIconViewProvider.ViewProvider(obj.ViewObject, "Stock") + PathIconViewProvider.ViewProvider(obj.ViewObject, "Stock") obj.ViewObject.Transparency = 90 obj.ViewObject.DisplayMode = "Wireframe" @@ -362,7 +367,7 @@ def _getBase(job): def CreateFromBase(job, neg=None, pos=None, placement=None): - PathLog.track(job.Label, neg, pos, placement) + Path.Log.track(job.Label, neg, pos, placement) base = _getBase(job) obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Stock") obj.Proxy = StockFromBase(obj, base) @@ -512,7 +517,7 @@ def CreateFromTemplate(job, template): or rotZ is not None or rotW is not None ): - PathLog.warning( + Path.Log.warning( "Corrupted or incomplete placement information in template - ignoring" ) @@ -551,30 +556,30 @@ def CreateFromTemplate(job, template): or zneg is not None or zpos is not None ): - PathLog.error( + Path.Log.error( "Corrupted or incomplete specification for creating stock from base - ignoring extent" ) return CreateFromBase(job, neg, pos, placement) if stockType == StockType.CreateBox: - PathLog.track(" create box") + Path.Log.track(" create box") length = template.get("length") width = template.get("width") height = template.get("height") extent = None if length is not None and width is not None and height is not None: - PathLog.track(" have extent") + Path.Log.track(" have extent") extent = FreeCAD.Vector( FreeCAD.Units.Quantity(length).Value, FreeCAD.Units.Quantity(width).Value, FreeCAD.Units.Quantity(height).Value, ) elif length is not None or width is not None or height is not None: - PathLog.error( + Path.Log.error( "Corrupted or incomplete size for creating a stock box - ignoring size" ) else: - PathLog.track( + Path.Log.track( " take placement (%s) and extent (%s) from model" % (placement, extent) ) @@ -588,18 +593,18 @@ def CreateFromTemplate(job, template): elif radius is not None or height is not None: radius = None height = None - PathLog.error( + Path.Log.error( "Corrupted or incomplete size for creating a stock cylinder - ignoring size" ) return CreateCylinder(job, radius, height, placement) - PathLog.error( + Path.Log.error( translate("PathStock", "Unsupported stock type named {}").format( stockType ) ) else: - PathLog.error( + Path.Log.error( translate( "PathStock", "Unsupported PathStock template version {}" ).format(template.get("version")) diff --git a/src/Mod/Path/Path/Main/__init__.py b/src/Mod/Path/Path/Main/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/PathAdaptive.py b/src/Mod/Path/Path/Op/Adaptive.py similarity index 98% rename from src/Mod/Path/PathScripts/PathAdaptive.py rename to src/Mod/Path/Path/Op/Adaptive.py index 3caf12e2ab..6c93c3e2c7 100644 --- a/src/Mod/Path/PathScripts/PathAdaptive.py +++ b/src/Mod/Path/Path/Op/Adaptive.py @@ -22,11 +22,9 @@ # * * # *************************************************************************** -import PathScripts.PathOp as PathOp -import PathScripts.PathUtils as PathUtils -import PathScripts.PathLog as PathLog -import PathScripts.PathGeom as PathGeom import Path +import Path.Op.Base as PathOp +import PathScripts.PathUtils as PathUtils import FreeCAD import time import json @@ -46,16 +44,16 @@ from lazy_loader.lazy_loader import LazyLoader Part = LazyLoader("Part", globals(), "Part") # TechDraw = LazyLoader('TechDraw', globals(), 'TechDraw') FeatureExtensions = LazyLoader( - "PathScripts.PathFeatureExtensions", globals(), "PathScripts.PathFeatureExtensions" + "Path.Op.FeatureExtension", globals(), "Path.Op.FeatureExtension" ) DraftGeomUtils = LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -653,7 +651,7 @@ def Execute(op, obj): if FreeCAD.GuiUp: sceneGraph = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() - PathLog.info("*** Adaptive toolpath processing started...\n") + Path.Log.info("*** Adaptive toolpath processing started...\n") # hide old toolpaths during recalculation obj.Path = Path.Path("(Calculating...)") @@ -680,7 +678,7 @@ def Execute(op, obj): # Get list of working edges for adaptive algorithm pathArray = op.pathArray if not pathArray: - PathLog.error("No wire data returned.") + Path.Log.error("No wire data returned.") return path2d = convertTo2d(pathArray) @@ -798,12 +796,12 @@ def Execute(op, obj): GenerateGCode(op, obj, adaptiveResults, helixDiameter) if not obj.StopProcessing: - PathLog.info("*** Done. Elapsed time: %f sec\n\n" % (time.time() - start)) + Path.Log.info("*** Done. Elapsed time: %f sec\n\n" % (time.time() - start)) obj.AdaptiveOutputState = adaptiveResults obj.AdaptiveInputState = inputStateObject else: - PathLog.info( + Path.Log.info( "*** Processing cancelled (after: %f sec).\n\n" % (time.time() - start) ) @@ -870,7 +868,7 @@ def _get_working_edges(op, obj): all_regions.append(f) # Second face-combining method attempted - horizontal = PathGeom.combineHorizontalFaces(all_regions) + horizontal = Path.Geom.combineHorizontalFaces(all_regions) if horizontal: obj.removalshape = Part.makeCompound(horizontal) for f in horizontal: @@ -927,11 +925,11 @@ class PathAdaptive(PathOp.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data diff --git a/src/Mod/Path/PathScripts/PathAreaOp.py b/src/Mod/Path/Path/Op/Area.py similarity index 92% rename from src/Mod/Path/PathScripts/PathAreaOp.py rename to src/Mod/Path/Path/Op/Area.py index ee2323a753..094627c58e 100644 --- a/src/Mod/Path/PathScripts/PathAreaOp.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -23,8 +23,7 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Path -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp +import Path.Op.Base as PathOp import PathScripts.PathUtils as PathUtils @@ -33,7 +32,6 @@ from lazy_loader.lazy_loader import LazyLoader Draft = LazyLoader("Draft", globals(), "Draft") Part = LazyLoader("Part", globals(), "Part") -PathGeom = LazyLoader("PathScripts.PathGeom", globals(), "PathScripts.PathGeom") __title__ = "Base class for PathArea based operations." @@ -44,10 +42,10 @@ __contributors__ = "russ4262 (Russell Johnson)" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -82,7 +80,7 @@ class ObjectOp(PathOp.ObjectOp): def initOperation(self, obj): """initOperation(obj) ... sets up standard Path.Area properties and calls initAreaOp(). Do not overwrite, overwrite initAreaOp(obj) instead.""" - PathLog.track() + Path.Log.track() # Debugging obj.addProperty("App::PropertyString", "AreaParams", "Path") @@ -113,16 +111,16 @@ class ObjectOp(PathOp.ObjectOp): The default implementation returns the job's Base.Shape""" if job: if job.Stock: - PathLog.debug( + Path.Log.debug( "job=%s base=%s shape=%s" % (job, job.Stock, job.Stock.Shape) ) return job.Stock.Shape else: - PathLog.warning( + Path.Log.warning( translate("PathAreaOp", "job %s has no Base.") % job.Label ) else: - PathLog.warning( + Path.Log.warning( translate("PathAreaOp", "no job for op %s found.") % obj.Label ) return None @@ -137,7 +135,7 @@ class ObjectOp(PathOp.ObjectOp): The base implementation takes a stab at determining Heights and Depths if the operations's Base changes. Do not overwrite, overwrite areaOpOnChanged(obj, prop) instead.""" - # PathLog.track(obj.Label, prop) + # Path.Log.track(obj.Label, prop) if prop in ["AreaParams", "PathParams", "removalshape"]: obj.setEditorMode(prop, 2) @@ -156,7 +154,7 @@ class ObjectOp(PathOp.ObjectOp): self.areaOpOnChanged(obj, prop) def opOnDocumentRestored(self, obj): - PathLog.track() + Path.Log.track() for prop in ["AreaParams", "PathParams", "removalshape"]: if hasattr(obj, prop): obj.setEditorMode(prop, 2) @@ -179,18 +177,18 @@ class ObjectOp(PathOp.ObjectOp): The base implementation sets the depths and heights based on the areaOpShapeForDepths() return value. Do not overwrite, overwrite areaOpSetDefaultValues(obj, job) instead.""" - PathLog.debug("opSetDefaultValues(%s, %s)" % (obj.Label, job.Label)) + Path.Log.debug("opSetDefaultValues(%s, %s)" % (obj.Label, job.Label)) if PathOp.FeatureDepths & self.opFeatures(obj): try: shape = self.areaOpShapeForDepths(obj, job) except Exception as ee: - PathLog.error(ee) + Path.Log.error(ee) shape = None # Set initial start and final depths if shape is None: - PathLog.debug("shape is None") + Path.Log.debug("shape is None") startDepth = 1.0 finalDepth = 0.0 else: @@ -203,12 +201,12 @@ class ObjectOp(PathOp.ObjectOp): obj.OpStartDepth.Value = startDepth obj.OpFinalDepth.Value = finalDepth - PathLog.debug( + Path.Log.debug( "Default OpDepths are Start: {}, and Final: {}".format( obj.OpStartDepth.Value, obj.OpFinalDepth.Value ) ) - PathLog.debug( + Path.Log.debug( "Default Depths are Start: {}, and Final: {}".format( startDepth, finalDepth ) @@ -223,7 +221,7 @@ class ObjectOp(PathOp.ObjectOp): def _buildPathArea(self, obj, baseobject, isHole, start, getsim): """_buildPathArea(obj, baseobject, isHole, start, getsim) ... internal function.""" - PathLog.track() + Path.Log.track() area = Path.Area() area.setPlane(PathUtils.makeWorkplane(baseobject)) area.add(baseobject) @@ -232,18 +230,18 @@ class ObjectOp(PathOp.ObjectOp): areaParams['SectionTolerance'] = 1e-07 heights = [i for i in self.depthparams] - PathLog.debug("depths: {}".format(heights)) + Path.Log.debug("depths: {}".format(heights)) area.setParams(**areaParams) obj.AreaParams = str(area.getParams()) - PathLog.debug("Area with params: {}".format(area.getParams())) + Path.Log.debug("Area with params: {}".format(area.getParams())) sections = area.makeSections( mode=0, project=self.areaOpUseProjection(obj), heights=heights ) - PathLog.debug("sections = %s" % sections) + Path.Log.debug("sections = %s" % sections) shapelist = [sec.getShape() for sec in sections] - PathLog.debug("shapelist = %s" % shapelist) + Path.Log.debug("shapelist = %s" % shapelist) pathParams = self.areaOpPathParams(obj, isHole) pathParams["shapes"] = shapelist @@ -267,10 +265,10 @@ class ObjectOp(PathOp.ObjectOp): obj.PathParams = str( {key: value for key, value in pathParams.items() if key != "shapes"} ) - PathLog.debug("Path with params: {}".format(obj.PathParams)) + Path.Log.debug("Path with params: {}".format(obj.PathParams)) (pp, end_vector) = Path.fromShapes(**pathParams) - PathLog.debug("pp: {}, end vector: {}".format(pp, end_vector)) + Path.Log.debug("pp: {}, end vector: {}".format(pp, end_vector)) self.endVector = end_vector simobj = None @@ -287,11 +285,11 @@ class ObjectOp(PathOp.ObjectOp): def _buildProfileOpenEdges(self, obj, edgeList, isHole, start, getsim): """_buildPathArea(obj, edgeList, isHole, start, getsim) ... internal function.""" - PathLog.track() + Path.Log.track() paths = [] heights = [i for i in self.depthparams] - PathLog.debug("depths: {}".format(heights)) + Path.Log.debug("depths: {}".format(heights)) for i in range(0, len(heights)): for baseShape in edgeList: hWire = Part.Wire(Part.__sortEdges__(baseShape.Edges)) @@ -316,9 +314,9 @@ class ObjectOp(PathOp.ObjectOp): x = verts[idx].X y = verts[idx].Y # Zero start value adjustments for Path.fromShapes() bug - if PathGeom.isRoughly(x, 0.0): + if Path.Geom.isRoughly(x, 0.0): x = 0.00001 - if PathGeom.isRoughly(y, 0.0): + if Path.Geom.isRoughly(y, 0.0): y = 0.00001 pathParams["start"] = FreeCAD.Vector(x, y, verts[0].Z) else: @@ -327,11 +325,11 @@ class ObjectOp(PathOp.ObjectOp): obj.PathParams = str( {key: value for key, value in pathParams.items() if key != "shapes"} ) - PathLog.debug("Path with params: {}".format(obj.PathParams)) + Path.Log.debug("Path with params: {}".format(obj.PathParams)) (pp, end_vector) = Path.fromShapes(**pathParams) paths.extend(pp.Commands) - PathLog.debug("pp: {}, end vector: {}".format(pp, end_vector)) + Path.Log.debug("pp: {}, end vector: {}".format(pp, end_vector)) self.endVector = end_vector simobj = None @@ -347,7 +345,7 @@ class ObjectOp(PathOp.ObjectOp): areaOpShapes(obj) ... the shape for path area to process areaOpUseProjection(obj) ... return true if operation can use projection instead.""" - PathLog.track() + Path.Log.track() # Instantiate class variables for operation reference self.endVector = None @@ -445,7 +443,7 @@ class ObjectOp(PathOp.ObjectOp): ) ) - PathLog.debug("obj.Name: " + str(obj.Name) + "\n\n") + Path.Log.debug("obj.Name: " + str(obj.Name) + "\n\n") return sims def areaOpRetractTool(self, obj): diff --git a/src/Mod/Path/PathScripts/PathOp.py b/src/Mod/Path/Path/Op/Base.py similarity index 95% rename from src/Mod/Path/PathScripts/PathOp.py rename to src/Mod/Path/Path/Op/Base.py index dc8e61c5eb..fce232ab41 100644 --- a/src/Mod/Path/PathScripts/PathOp.py +++ b/src/Mod/Path/Path/Op/Base.py @@ -24,10 +24,7 @@ import FreeCAD from PathScripts.PathUtils import waiting_effects from PySide.QtCore import QT_TRANSLATE_NOOP import Path -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathUtil as PathUtil +import Path.Base.Util as PathUtil import PathScripts.PathUtils as PathUtils import math import time @@ -44,10 +41,10 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Base class and properties implementation for all Path operations." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -164,7 +161,7 @@ class ObjectOp(object): obj.setEditorMode("OpStockZMin", 1) # read-only def __init__(self, obj, name, parentJob=None): - PathLog.track() + Path.Log.track() obj.addProperty( "App::PropertyBool", @@ -336,8 +333,8 @@ class ObjectOp(object): ) for n in self.opPropertyEnumerations(): - PathLog.debug("n: {}".format(n)) - PathLog.debug("n[0]: {} n[1]: {}".format(n[0], n[1])) + Path.Log.debug("n: {}".format(n)) + Path.Log.debug("n[0]: {} n[1]: {}".format(n[0], n[1])) if hasattr(obj, n[0]): setattr(obj, n[0], n[1]) @@ -390,11 +387,11 @@ class ObjectOp(object): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -410,13 +407,13 @@ class ObjectOp(object): obj.setEditorMode("OpFinalDepth", 2) def onDocumentRestored(self, obj): - PathLog.track() + Path.Log.track() features = self.opFeatures(obj) if ( FeatureBaseGeometry & features and "App::PropertyLinkSubList" == obj.getTypeIdOfProperty("Base") ): - PathLog.info("Replacing link property with global link (%s)." % obj.State) + Path.Log.info("Replacing link property with global link (%s)." % obj.State) base = obj.Base obj.removeProperty("Base") self.addBaseProperty(obj) @@ -580,8 +577,8 @@ class ObjectOp(object): obj.OpToolDiameter = obj.ToolController.Tool.Diameter if FeatureCoolant & features: - PathLog.track() - PathLog.debug(obj.getEnumerationsOfProperty("CoolantMode")) + Path.Log.track() + Path.Log.debug(obj.getEnumerationsOfProperty("CoolantMode")) obj.CoolantMode = job.SetupSheet.CoolantMode if FeatureDepths & features: @@ -635,11 +632,11 @@ class ObjectOp(object): if not job: if not ignoreErrors: - PathLog.error(translate("Path", "No parent job found for operation.")) + Path.Log.error(translate("Path", "No parent job found for operation.")) return False if not job.Model.Group: if not ignoreErrors: - PathLog.error( + Path.Log.error( translate("Path", "Parent job %s doesn't have a base object") % job.Label ) @@ -694,7 +691,7 @@ class ObjectOp(object): zmin = max(zmin, faceZmin(bb, fbb)) zmax = max(zmax, fbb.ZMax) except Part.OCCError as e: - PathLog.error(e) + Path.Log.error(e) else: # clearing with stock boundaries @@ -704,12 +701,12 @@ class ObjectOp(object): if FeatureDepths & self.opFeatures(obj): # first set update final depth, it's value is not negotiable - if not PathGeom.isRoughly(obj.OpFinalDepth.Value, zmin): + if not Path.Geom.isRoughly(obj.OpFinalDepth.Value, zmin): obj.OpFinalDepth = zmin zmin = obj.OpFinalDepth.Value def minZmax(z): - if hasattr(obj, "StepDown") and not PathGeom.isRoughly( + if hasattr(obj, "StepDown") and not Path.Geom.isRoughly( obj.StepDown.Value, 0 ): return z + obj.StepDown.Value @@ -721,7 +718,7 @@ class ObjectOp(object): zmax = minZmax(zmin) # update start depth if requested and required - if not PathGeom.isRoughly(obj.OpStartDepth.Value, zmax): + if not Path.Geom.isRoughly(obj.OpStartDepth.Value, zmax): obj.OpStartDepth = zmax else: # every obj has a StartDepth @@ -738,7 +735,7 @@ class ObjectOp(object): for sub in sublist: o.Shape.getElement(sub) except Part.OCCError: - PathLog.error( + Path.Log.error( "{} - stale base geometry detected - clearing.".format(obj.Label) ) obj.Base = [] @@ -766,7 +763,7 @@ class ObjectOp(object): Finally the base implementation adds a rapid move to clearance height and assigns the receiver's Path property from the command list. """ - PathLog.track() + Path.Log.track() if not obj.Active: path = Path.Path("(inactive operation)") @@ -782,7 +779,7 @@ class ObjectOp(object): if FeatureTool & self.opFeatures(obj): tc = obj.ToolController if tc is None or tc.ToolNumber == 0: - PathLog.error( + Path.Log.error( translate( "Path", "No Tool Controller is selected. We need a tool to build a Path.", @@ -796,7 +793,7 @@ class ObjectOp(object): self.horizRapid = tc.HorizRapid.Value tool = tc.Proxy.getTool(tc) if not tool or float(tool.Diameter) == 0: - PathLog.error( + Path.Log.error( translate( "Path", "No Tool found or diameter is zero. We need a tool to build a Path.", @@ -836,7 +833,7 @@ class ObjectOp(object): tc = obj.ToolController if tc is None or tc.ToolNumber == 0: - PathLog.error(translate("Path", "No Tool Controller selected.")) + Path.Log.error(translate("Path", "No Tool Controller selected.")) return translate("Path", "Tool Error") hFeedrate = tc.HorizFeed.Value @@ -846,8 +843,8 @@ class ObjectOp(object): if ( hFeedrate == 0 or vFeedrate == 0 - ) and not PathPreferences.suppressAllSpeedsWarning(): - PathLog.warning( + ) and not Path.Preferences.suppressAllSpeedsWarning(): + Path.Log.warning( translate( "Path", "Tool Controller feedrates required to calculate the cycle time.", @@ -857,8 +854,8 @@ class ObjectOp(object): if ( hRapidrate == 0 or vRapidrate == 0 - ) and not PathPreferences.suppressRapidSpeedsWarning(): - PathLog.warning( + ) and not Path.Preferences.suppressRapidSpeedsWarning(): + Path.Log.warning( translate( "Path", "Add Tool Controller Rapid Speeds on the SetupSheet for more accurate cycle times.", @@ -877,7 +874,7 @@ class ObjectOp(object): return cycleTime def addBase(self, obj, base, sub): - PathLog.track(obj, base, sub) + Path.Log.track(obj, base, sub) base = PathUtil.getPublicObject(base) if self._setBaseAndStock(obj): @@ -892,7 +889,7 @@ class ObjectOp(object): for p, el in baselist: if p == base and sub in el: - PathLog.notice( + Path.Log.notice( ( translate("Path", "Base object %s.%s already in the list") + "\n" @@ -905,7 +902,7 @@ class ObjectOp(object): baselist.append((base, sub)) obj.Base = baselist else: - PathLog.notice( + Path.Log.notice( ( translate("Path", "Base object %s.%s rejected by operation") + "\n" diff --git a/src/Mod/Path/PathScripts/PathCircularHoleBase.py b/src/Mod/Path/Path/Op/CircularHoleBase.py similarity index 93% rename from src/Mod/Path/PathScripts/PathCircularHoleBase.py rename to src/Mod/Path/Path/Op/CircularHoleBase.py index d8b3fa0abe..885b5ca031 100644 --- a/src/Mod/Path/PathScripts/PathCircularHoleBase.py +++ b/src/Mod/Path/Path/Op/CircularHoleBase.py @@ -22,9 +22,9 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.drillableLib as drillableLib +import Path +import Path.Op.Base as PathOp +import Path.Base.Drillable as Drillable # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -44,10 +44,10 @@ translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectOp(PathOp.ObjectOp): @@ -109,7 +109,7 @@ class ObjectOp(PathOp.ObjectOp): # for all other shapes the diameter is just the dimension in X. # This may be inaccurate as the BoundBox is calculated on the tessellated geometry - PathLog.warning( + Path.Log.warning( translate( "Path", "Hole diameter may be inaccurate due to tessellation on face. Consider selecting hole edge.", @@ -117,7 +117,7 @@ class ObjectOp(PathOp.ObjectOp): ) return shape.BoundBox.XLength except Part.OCCError as e: - PathLog.error(e) + Path.Log.error(e) return 0 @@ -141,9 +141,9 @@ class ObjectOp(PathOp.ObjectOp): if len(shape.Edges) == 1 and type(shape.Edges[0].Curve) == Part.Circle: return shape.Edges[0].Curve.Center except Part.OCCError as e: - PathLog.error(e) + Path.Log.error(e) - PathLog.error( + Path.Log.error( translate( "Path", "Feature %s.%s cannot be processed as a circular hole - please remove from Base geometry list.", @@ -164,7 +164,7 @@ class ObjectOp(PathOp.ObjectOp): drillable features are added to Base. In this case appropriate values for depths are also calculated and assigned. Do not overwrite, implement circularHoleExecute(obj, holes) instead.""" - PathLog.track() + Path.Log.track() def haveLocations(self, obj): if PathOp.FeatureLocations & self.opFeatures(obj): @@ -174,7 +174,7 @@ class ObjectOp(PathOp.ObjectOp): holes = [] for base, subs in obj.Base: for sub in subs: - PathLog.debug("processing {} in {}".format(sub, base.Name)) + Path.Log.debug("processing {} in {}".format(sub, base.Name)) if self.isHoleEnabled(obj, base, sub): pos = self.holePosition(obj, base, sub) if pos: @@ -202,7 +202,7 @@ class ObjectOp(PathOp.ObjectOp): def findAllHoles(self, obj): """findAllHoles(obj) ... find all holes of all base models and assign as features.""" - PathLog.track() + Path.Log.track() job = self.getJob(obj) if not job: return @@ -213,7 +213,7 @@ class ObjectOp(PathOp.ObjectOp): features = [] for base in self.model: features.extend( - drillableLib.getDrillableTargets( + Drillable.getDrillableTargets( base, ToolDiameter=tooldiameter, vector=matchvector ) ) diff --git a/src/Mod/Path/PathScripts/PathCustom.py b/src/Mod/Path/Path/Op/Custom.py similarity index 92% rename from src/Mod/Path/PathScripts/PathCustom.py rename to src/Mod/Path/Path/Op/Custom.py index 17b03f830d..2d24957329 100644 --- a/src/Mod/Path/PathScripts/PathCustom.py +++ b/src/Mod/Path/Path/Op/Custom.py @@ -22,9 +22,7 @@ import FreeCAD import Path - -import PathScripts.PathOp as PathOp -import PathScripts.PathLog as PathLog +import Path.Op.Base as PathOp from PySide.QtCore import QT_TRANSLATE_NOOP @@ -35,10 +33,10 @@ __doc__ = "Path Custom object and FreeCAD command" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate diff --git a/src/Mod/Path/PathScripts/PathDeburr.py b/src/Mod/Path/Path/Op/Deburr.py similarity index 95% rename from src/Mod/Path/PathScripts/PathDeburr.py rename to src/Mod/Path/Path/Op/Deburr.py index 98da2a488f..9ad1893ac9 100644 --- a/src/Mod/Path/PathScripts/PathDeburr.py +++ b/src/Mod/Path/Path/Op/Deburr.py @@ -22,11 +22,10 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathEngraveBase as PathEngraveBase -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.PathOpTools as PathOpTools +import Path +import Path.Op.Base as PathOp +import Path.Op.EngraveBase as PathEngraveBase +import Path.Op.Util as PathOpUtil import math from PySide.QtCore import QT_TRANSLATE_NOOP @@ -43,10 +42,10 @@ __doc__ = "Deburr operation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -61,7 +60,7 @@ def toolDepthAndOffset(width, extraDepth, tool, printInfo): suppressInfo = False if hasattr(tool, "CuttingEdgeAngle"): angle = float(tool.CuttingEdgeAngle) - if PathGeom.isRoughly(angle, 180) or PathGeom.isRoughly(angle, 0): + if Path.Geom.isRoughly(angle, 180) or Path.Geom.isRoughly(angle, 0): angle = 180 toolOffset = float(tool.Diameter) / 2 else: @@ -95,7 +94,7 @@ def toolDepthAndOffset(width, extraDepth, tool, printInfo): tan = math.tan(math.radians(angle / 2)) - toolDepth = 0 if PathGeom.isRoughly(tan, 0) else width / tan + toolDepth = 0 if Path.Geom.isRoughly(tan, 0) else width / tan depth = toolDepth + extraDepth extraOffset = -width if angle == 180 else (extraDepth / tan) offset = toolOffset + extraOffset @@ -118,7 +117,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): ) def initOperation(self, obj): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) obj.addProperty( "App::PropertyDistance", "Width", @@ -197,12 +196,12 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): # data[k] = [tup[idx] for tup in v] data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -210,7 +209,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): obj.setEditorMode("Join", 2) # hide for now def opExecute(self, obj): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) if not hasattr(self, "printInfo"): self.printInfo = True try: @@ -224,7 +223,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): # QtGui.QMessageBox.information(None, "Tool Error", msg) # return - PathLog.track(obj.Label, depth, offset) + Path.Log.track(obj.Label, depth, offset) self.basewires = [] self.adjusted_basewires = [] @@ -410,7 +409,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): for w in basewires: self.adjusted_basewires.append(w) - wire = PathOpTools.offsetWire(w, base.Shape, offset, True, side) + wire = PathOpUtil.offsetWire(w, base.Shape, offset, True, side) if wire: wires.append(wire) @@ -431,7 +430,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): zValues.append(z) zValues.append(depth) - PathLog.track(obj.Label, depth, zValues) + Path.Log.track(obj.Label, depth, zValues) if obj.EntryPoint < 0: obj.EntryPoint = 0 @@ -444,7 +443,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): return base not in self.model def opSetDefaultValues(self, obj, job): - PathLog.track(obj.Label, job.Label) + Path.Log.track(obj.Label, job.Label) obj.Width = "1 mm" obj.ExtraDepth = "0.5 mm" obj.Join = "Round" diff --git a/src/Mod/Path/PathScripts/PathDrilling.py b/src/Mod/Path/Path/Op/Drilling.py similarity index 95% rename from src/Mod/Path/PathScripts/PathDrilling.py rename to src/Mod/Path/Path/Op/Drilling.py index 8809b2dc05..b21a03dfb4 100644 --- a/src/Mod/Path/PathScripts/PathDrilling.py +++ b/src/Mod/Path/Path/Op/Drilling.py @@ -24,15 +24,14 @@ from __future__ import print_function -from Generators import drill_generator as generator import FreeCAD import Part import Path -import PathFeedRate -import PathMachineState -import PathScripts.PathCircularHoleBase as PathCircularHoleBase -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp +import Path.Base.FeedRate as PathFeedRate +import Path.Base.Generator.drill as drill +import Path.Base.MachineState as PathMachineState +import Path.Op.Base as PathOp +import Path.Op.CircularHoleBase as PathCircularHoleBase import PathScripts.PathUtils as PathUtils from PySide.QtCore import QT_TRANSLATE_NOOP @@ -43,10 +42,10 @@ __doc__ = "Path Drilling operation." __contributors__ = "IMBack!" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -84,11 +83,11 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -180,7 +179,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): def circularHoleExecute(self, obj, holes): """circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.""" - PathLog.track() + Path.Log.track() machine = PathMachineState.MachineState() self.commandlist.append(Path.Command("(Begin Drilling)")) @@ -220,7 +219,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): # iterate the edgelist and generate gcode for edge in edgelist: - PathLog.debug(edge) + Path.Log.debug(edge) # move to hole location @@ -249,7 +248,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): chipBreak = (obj.chipBreakEnabled and obj.PeckEnabled) try: - drillcommands = generator.generate( + drillcommands = drill.generate( edge, dwelltime, peckdepth, @@ -259,7 +258,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): ) except ValueError as e: # any targets that fail the generator are ignored - PathLog.info(e) + Path.Log.info(e) continue for command in drillcommands: diff --git a/src/Mod/Path/PathScripts/PathEngrave.py b/src/Mod/Path/Path/Op/Engrave.py similarity index 91% rename from src/Mod/Path/PathScripts/PathEngrave.py rename to src/Mod/Path/Path/Op/Engrave.py index ca79b735d6..022bea8409 100644 --- a/src/Mod/Path/PathScripts/PathEngrave.py +++ b/src/Mod/Path/Path/Op/Engrave.py @@ -22,9 +22,8 @@ import FreeCAD import Path -import PathScripts.PathEngraveBase as PathEngraveBase -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp +import Path.Op.Base as PathOp +import Path.Op.EngraveBase as PathEngraveBase import PathScripts.PathUtils as PathUtils from PySide.QtCore import QT_TRANSLATE_NOOP @@ -32,10 +31,10 @@ from PySide.QtCore import QT_TRANSLATE_NOOP __doc__ = "Class and implementation of Path Engrave operation" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -101,12 +100,12 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): def opExecute(self, obj): """opExecute(obj) ... process engraving operation""" - PathLog.track() + Path.Log.track() jobshapes = [] if len(obj.Base) >= 1: # user has selected specific subelements - PathLog.track(len(obj.Base)) + Path.Log.track(len(obj.Base)) wires = [] for base, subs in obj.Base: edges = [] @@ -129,9 +128,9 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): elif len(obj.BaseShapes) > 0: # user added specific shapes jobshapes.extend([base.Shape for base in obj.BaseShapes]) else: - PathLog.track(self.model) + Path.Log.track(self.model) for base in self.model: - PathLog.track(base.Label) + Path.Log.track(base.Label) if base.isDerivedFrom("Part::Part2DObject"): jobshapes.append(base.Shape) elif base.isDerivedFrom("Sketcher::SketchObject"): @@ -140,11 +139,11 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): jobshapes.append(base.Shape) if len(jobshapes) > 0: - PathLog.debug("processing {} jobshapes".format(len(jobshapes))) + Path.Log.debug("processing {} jobshapes".format(len(jobshapes))) wires = [] for shape in jobshapes: shapeWires = shape.Wires - PathLog.debug("jobshape has {} edges".format(len(shape.Edges))) + Path.Log.debug("jobshape has {} edges".format(len(shape.Edges))) self.commandlist.append( Path.Command( "G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid} @@ -153,7 +152,7 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): self.buildpathocc(obj, shapeWires, self.getZValues(obj)) wires.extend(shapeWires) self.wires = wires - PathLog.debug( + Path.Log.debug( "processing {} jobshapes -> {} wires".format(len(jobshapes), len(wires)) ) # the last command is a move to clearance, which is automatically added by PathOp diff --git a/src/Mod/Path/PathScripts/PathEngraveBase.py b/src/Mod/Path/Path/Op/EngraveBase.py similarity index 84% rename from src/Mod/Path/PathScripts/PathEngraveBase.py rename to src/Mod/Path/Path/Op/EngraveBase.py index 71810d1fb3..0a235bb356 100644 --- a/src/Mod/Path/PathScripts/PathEngraveBase.py +++ b/src/Mod/Path/Path/Op/EngraveBase.py @@ -22,10 +22,8 @@ from lazy_loader.lazy_loader import LazyLoader import Path -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.PathOpTools as PathOpTools +import Path.Op.Base as PathOp +import Path.Op.Util as PathOpUtil import copy __doc__ = "Base class for all ops in the engrave family." @@ -35,10 +33,10 @@ DraftGeomUtils = LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") Part = LazyLoader("Part", globals(), "Part") if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectOp(PathOp.ObjectOp): @@ -61,11 +59,11 @@ class ObjectOp(PathOp.ObjectOp): def buildpathocc(self, obj, wires, zValues, relZ=False, forward=True, start_idx=0): """buildpathocc(obj, wires, zValues, relZ=False) ... internal helper function to generate engraving commands.""" - PathLog.track(obj.Label, len(wires), zValues) + Path.Log.track(obj.Label, len(wires), zValues) decomposewires = [] for wire in wires: - decomposewires.extend(PathOpTools.makeWires(wire.Edges)) + decomposewires.extend(PathOpUtil.makeWires(wire.Edges)) wires = decomposewires for wire in wires: @@ -76,15 +74,15 @@ class ObjectOp(PathOp.ObjectOp): start_idx = obj.StartVertex edges = wire.Edges - # edges = copy.copy(PathOpTools.orientWire(offset, forward).Edges) - # PathLog.track("wire: {} offset: {}".format(len(wire.Edges), len(edges))) + # edges = copy.copy(PathOpUtil.orientWire(offset, forward).Edges) + # Path.Log.track("wire: {} offset: {}".format(len(wire.Edges), len(edges))) # edges = Part.sortEdges(edges)[0] - # PathLog.track("edges: {}".format(len(edges))) + # Path.Log.track("edges: {}".format(len(edges))) last = None for z in zValues: - PathLog.debug(z) + Path.Log.debug(z) if last: self.appendCommand( Path.Command("G1", {"X": last.x, "Y": last.y, "Z": last.z}), @@ -99,19 +97,19 @@ class ObjectOp(PathOp.ObjectOp): edges = edges[start_idx:] + edges[:start_idx] for edge in edges: - PathLog.debug( + Path.Log.debug( "points: {} -> {}".format( edge.Vertexes[0].Point, edge.Vertexes[-1].Point ) ) - PathLog.debug( + Path.Log.debug( "valueat {} -> {}".format( edge.valueAt(edge.FirstParameter), edge.valueAt(edge.LastParameter), ) ) if first and (not last or not wire.isClosed()): - PathLog.debug("processing first edge entry") + Path.Log.debug("processing first edge entry") # we set the first move to our first point last = edge.Vertexes[0].Point @@ -139,13 +137,13 @@ class ObjectOp(PathOp.ObjectOp): ) first = False - if PathGeom.pointsCoincide(last, edge.valueAt(edge.FirstParameter)): - # if PathGeom.pointsCoincide(last, edge.Vertexes[0].Point): - for cmd in PathGeom.cmdsForEdge(edge): + if Path.Geom.pointsCoincide(last, edge.valueAt(edge.FirstParameter)): + # if Path.Geom.pointsCoincide(last, edge.Vertexes[0].Point): + for cmd in Path.Geom.cmdsForEdge(edge): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[-1].Point else: - for cmd in PathGeom.cmdsForEdge(edge, True): + for cmd in Path.Geom.cmdsForEdge(edge, True): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[0].Point self.commandlist.append( diff --git a/src/Mod/Path/PathScripts/PathFeatureExtensions.py b/src/Mod/Path/Path/Op/FeatureExtension.py similarity index 90% rename from src/Mod/Path/PathScripts/PathFeatureExtensions.py rename to src/Mod/Path/Path/Op/FeatureExtension.py index 9a734de260..fd14420453 100644 --- a/src/Mod/Path/PathScripts/PathFeatureExtensions.py +++ b/src/Mod/Path/Path/Op/FeatureExtension.py @@ -23,8 +23,7 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Part -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog +import Path import math # lazily loaded modules @@ -40,10 +39,10 @@ __doc__ = "Class and implementation of face extensions features." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -56,7 +55,7 @@ def endPoints(edgeOrWire): pts.extend([e.valueAt(e.LastParameter) for e in edgeOrWire.Edges]) unique = [] for p in pts: - cnt = len([p2 for p2 in pts if PathGeom.pointsCoincide(p, p2)]) + cnt = len([p2 for p2 in pts if Path.Geom.pointsCoincide(p, p2)]) if 1 == cnt: unique.append(p) @@ -64,7 +63,7 @@ def endPoints(edgeOrWire): pfirst = edgeOrWire.valueAt(edgeOrWire.FirstParameter) plast = edgeOrWire.valueAt(edgeOrWire.LastParameter) - if PathGeom.pointsCoincide(pfirst, plast): + if Path.Geom.pointsCoincide(pfirst, plast): return None return [pfirst, plast] @@ -73,7 +72,7 @@ def endPoints(edgeOrWire): def includesPoint(p, pts): """includesPoint(p, pts) ... answer True if the collection of pts includes the point p""" for pt in pts: - if PathGeom.pointsCoincide(p, pt): + if Path.Geom.pointsCoincide(p, pt): return True return False @@ -95,7 +94,7 @@ def selectOffsetWire(feature, wires): def extendWire(feature, wire, length): """extendWire(wire, length) ... return a closed Wire which extends wire by length""" - PathLog.track(length) + Path.Log.track(length) if not length or length == 0: return None @@ -103,7 +102,7 @@ def extendWire(feature, wire, length): try: off2D = wire.makeOffset2D(length) except FreeCAD.Base.FreeCADError as ee: - PathLog.debug(ee) + Path.Log.debug(ee) return None endPts = endPoints(wire) # Assumes wire is NOT closed if endPts: @@ -157,7 +156,7 @@ def readObjExtensionFeature(obj): def getExtensions(obj): - PathLog.debug("getExtenstions()") + Path.Log.debug("getExtenstions()") extensions = [] i = 0 @@ -170,7 +169,7 @@ def getExtensions(obj): def setExtensions(obj, extensions): - PathLog.track(obj.Label, len(extensions)) + Path.Log.track(obj.Label, len(extensions)) obj.ExtensionFeature = [(ext.obj, ext.getSubLink()) for ext in extensions] @@ -218,7 +217,7 @@ class Extension(object): DirectionY = 2 def __init__(self, op, obj, feature, sub, length, direction): - PathLog.debug( + Path.Log.debug( "Extension(%s, %s, %s, %.2f, %s" % (obj.Label, feature, sub, length, direction) ) @@ -229,7 +228,7 @@ class Extension(object): self.length = length self.direction = direction self.extFaces = None - self.isDebug = True if PathLog.getLevel(PathLog.thisModule()) == 4 else False + self.isDebug = True if Path.Log.getLevel(Path.Log.thisModule()) == 4 else False self.avoid = False if sub.startswith("Avoid_"): @@ -241,12 +240,12 @@ class Extension(object): return "%s:%s" % (self.feature, self.sub) def _extendEdge(self, feature, e0, direction): - PathLog.track(feature, e0, direction) + Path.Log.track(feature, e0, direction) if isinstance(e0.Curve, Part.Line) or isinstance(e0.Curve, Part.LineSegment): e2 = e0.copy() off = self.length.Value * direction e2.translate(off) - e2 = PathGeom.flipEdge(e2) + e2 = Path.Geom.flipEdge(e2) e1 = Part.Edge( Part.LineSegment( e0.valueAt(e0.LastParameter), e2.valueAt(e2.FirstParameter) @@ -269,7 +268,7 @@ class Extension(object): else: numbers = [self.sub[4:]] - PathLog.debug("_getEdgeNumbers() -> %s" % numbers) + Path.Log.debug("_getEdgeNumbers() -> %s" % numbers) return numbers def _getEdgeNames(self): @@ -293,9 +292,9 @@ class Extension(object): e0 = wire.Edges[0] midparam = e0.FirstParameter + 0.5 * (e0.LastParameter - e0.FirstParameter) tangent = e0.tangentAt(midparam) - PathLog.track("tangent", tangent, self.feature, self.sub) + Path.Log.track("tangent", tangent, self.feature, self.sub) normal = tangent.cross(FreeCAD.Vector(0, 0, 1)) - if PathGeom.pointsCoincide(normal, FreeCAD.Vector(0, 0, 0)): + if Path.Geom.pointsCoincide(normal, FreeCAD.Vector(0, 0, 0)): return None return self._getDirectedNormal(e0.valueAt(midparam), normal.normalize()) @@ -323,11 +322,11 @@ class Extension(object): """_getRegularWire()... Private method to retrieve the extension area, pertaining to the feature and sub element provided at class instantiation, as a closed wire. If no closed wire is possible, a `None` value is returned.""" - PathLog.track() + Path.Log.track() length = self.length.Value - if PathGeom.isRoughly(0, length) or not self.sub: - PathLog.debug("no extension, length=%.2f, sub=%s" % (length, self.sub)) + if Path.Geom.isRoughly(0, length) or not self.sub: + Path.Log.debug("no extension, length=%.2f, sub=%s" % (length, self.sub)) return None feature = self.obj.Shape.getElement(self.feature) @@ -335,10 +334,10 @@ class Extension(object): sub = Part.Wire(Part.sortEdges(edges)[0]) if 1 == len(edges): - PathLog.debug("Extending single edge wire") + Path.Log.debug("Extending single edge wire") edge = edges[0] if Part.Circle == type(edge.Curve): - PathLog.debug("is Part.Circle") + Path.Log.debug("is Part.Circle") circle = edge.Curve # for a circle we have to figure out if it's a hole or a cylinder p0 = edge.valueAt(edge.FirstParameter) @@ -347,14 +346,14 @@ class Extension(object): if direction is None: return None - if PathGeom.pointsCoincide(normal, direction): + if Path.Geom.pointsCoincide(normal, direction): r = circle.Radius - length else: r = circle.Radius + length # assuming the offset produces a valid circle - go for it if r > 0: - PathLog.debug("radius > 0 - extend outward") + Path.Log.debug("radius > 0 - extend outward") e3 = Part.makeCircle( r, circle.Center, @@ -365,7 +364,7 @@ class Extension(object): # Determine if rotational alignment is necessary for new arc rotationAdjustment = arcAdjustmentAngle(edge, e3) - if not PathGeom.isRoughly(rotationAdjustment, 0.0): + if not Path.Geom.isRoughly(rotationAdjustment, 0.0): e3.rotate( edge.Curve.Center, FreeCAD.Vector(0.0, 0.0, 1.0), @@ -373,7 +372,7 @@ class Extension(object): ) if endPoints(edge): - PathLog.debug("Make section of donut") + Path.Log.debug("Make section of donut") # need to construct the arc slice e0 = Part.makeLine( edge.valueAt(edge.FirstParameter), @@ -397,22 +396,22 @@ class Extension(object): self.extFaces = [self._makeCircularExtFace(edge, extWire)] return extWire - PathLog.debug("radius < 0 - extend inward") + Path.Log.debug("radius < 0 - extend inward") # the extension is bigger than the hole - so let's just cover the whole hole if endPoints(edge): # if the resulting arc is smaller than the radius, create a pie slice - PathLog.track() + Path.Log.track() center = circle.Center e0 = Part.makeLine(center, edge.valueAt(edge.FirstParameter)) e2 = Part.makeLine(edge.valueAt(edge.LastParameter), center) return Part.Wire([e0, edge, e2]) - PathLog.track() + Path.Log.track() return Part.Wire([edge]) else: - PathLog.debug("else is NOT Part.Circle") - PathLog.track(self.feature, self.sub, type(edge.Curve), endPoints(edge)) + Path.Log.debug("else is NOT Part.Circle") + Path.Log.track(self.feature, self.sub, type(edge.Curve), endPoints(edge)) direction = self._getDirection(sub) if direction is None: return None @@ -420,18 +419,18 @@ class Extension(object): return self._extendEdge(feature, edges[0], direction) elif sub.isClosed(): - PathLog.debug("Extending multi-edge closed wire") + Path.Log.debug("Extending multi-edge closed wire") subFace = Part.Face(sub) featFace = Part.Face(feature.Wires[0]) isOutside = True - if not PathGeom.isRoughly(featFace.Area, subFace.Area): + if not Path.Geom.isRoughly(featFace.Area, subFace.Area): length = -1.0 * length isOutside = False try: off2D = sub.makeOffset2D(length) except FreeCAD.Base.FreeCADError as ee: - PathLog.debug(ee) + Path.Log.debug(ee) return None if isOutside: @@ -440,7 +439,7 @@ class Extension(object): self.extFaces = [subFace.cut(Part.Face(off2D))] return off2D - PathLog.debug("Extending multi-edge open wire") + Path.Log.debug("Extending multi-edge open wire") extendedWire = extendWire(feature, sub, length) if extendedWire is None: return extendedWire @@ -538,7 +537,7 @@ def getExtendOutlineFace( face, extension, removeHoles=remHoles, plane=face, tolerance=offset_tolerance ) if not offset_face: - PathLog.error("Failed to offset a selected face.") + Path.Log.error("Failed to offset a selected face.") return None # Apply collision detection by limiting extended face using base shape @@ -560,9 +559,9 @@ def getExtendOutlineFace( bbx = f.BoundBox zNorm = abs(f.normalAt(0.0, 0.0).z) if ( - PathGeom.isRoughly(zNorm, 1.0) - and PathGeom.isRoughly(bbx.ZMax - bbx.ZMin, 0.0) - and PathGeom.isRoughly(bbx.ZMin, face.BoundBox.ZMin) + Path.Geom.isRoughly(zNorm, 1.0) + and Path.Geom.isRoughly(bbx.ZMax - bbx.ZMin, 0.0) + and Path.Geom.isRoughly(bbx.ZMin, face.BoundBox.ZMin) ): if bbx.ZMin < zmin: bottom_faces.append(f) @@ -579,7 +578,7 @@ def getExtendOutlineFace( return extended - PathLog.error("No bottom face for extend outline.") + Path.Log.error("No bottom face for extend outline.") return None @@ -610,7 +609,7 @@ def getWaterlineFace(base_shape, face): # Get top face(s) of envelope at face height rawList = list() for f in env.Faces: - if PathGeom.isRoughly(f.BoundBox.ZMin, faceHeight): + if Path.Geom.isRoughly(f.BoundBox.ZMin, faceHeight): rawList.append(f) # make compound and extrude downward rawComp = Part.makeCompound(rawList) diff --git a/src/Mod/Path/PathScripts/PathAdaptiveGui.py b/src/Mod/Path/Path/Op/Gui/Adaptive.py similarity index 97% rename from src/Mod/Path/PathScripts/PathAdaptiveGui.py rename to src/Mod/Path/Path/Op/Gui/Adaptive.py index 4b42a2fd92..4bc069470b 100644 --- a/src/Mod/Path/PathScripts/PathAdaptiveGui.py +++ b/src/Mod/Path/Path/Op/Gui/Adaptive.py @@ -21,11 +21,11 @@ # * * # *************************************************************************** -import PathScripts.PathOpGui as PathOpGui -from PySide import QtCore -import PathScripts.PathAdaptive as PathAdaptive -import PathScripts.PathFeatureExtensionsGui as PathFeatureExtensionsGui import FreeCADGui +import Path.Op.Adaptive as PathAdaptive +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Gui.FeatureExtension as PathFeatureExtensionsGui +from PySide import QtCore class TaskPanelOpPage(PathOpGui.TaskPanelPage): diff --git a/src/Mod/Path/PathScripts/PathArray.py b/src/Mod/Path/Path/Op/Gui/Array.py similarity index 98% rename from src/Mod/Path/PathScripts/PathArray.py rename to src/Mod/Path/Path/Op/Gui/Array.py index 295a34f72b..b7daea3400 100644 --- a/src/Mod/Path/PathScripts/PathArray.py +++ b/src/Mod/Path/Path/Op/Gui/Array.py @@ -24,8 +24,7 @@ import FreeCAD import FreeCADGui import Path import PathScripts -from PathScripts import PathLog -from PathScripts.PathDressup import toolController +from Path.Dressup.Utils import toolController from PySide import QtCore import math import random @@ -373,7 +372,7 @@ class PathArray: path data for the requested path array.""" if len(self.baseList) == 0: - PathLog.error(translate("PathArray", "No base objects for PathArray.")) + Path.Log.error(translate("PathArray", "No base objects for PathArray.")) return None base = self.baseList @@ -389,7 +388,7 @@ class PathArray: if b_tool_controller != toolController(base[0]): # this may be important if Job output is split by tool controller - PathLog.warning( + Path.Log.warning( translate( "PathArray", "Arrays of paths having different tool controllers are handled according to the tool controller of the first path.", @@ -540,14 +539,14 @@ class CommandPathArray: # 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("Path.Op.Gui.Array") FreeCADGui.addModule("PathScripts.PathUtils") FreeCADGui.doCommand( 'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Array")' ) - FreeCADGui.doCommand("PathScripts.PathArray.ObjectArray(obj)") + FreeCADGui.doCommand("Path.Op.Gui.Array.ObjectArray(obj)") baseString = "[%s]" % ",".join( ["FreeCAD.ActiveDocument.%s" % sel.Name for sel in selection] diff --git a/src/Mod/Path/PathScripts/PathOpGui.py b/src/Mod/Path/Path/Op/Gui/Base.py similarity index 95% rename from src/Mod/Path/PathScripts/PathOpGui.py rename to src/Mod/Path/Path/Op/Gui/Base.py index 62d9d80080..9f61f5d5cf 100644 --- a/src/Mod/Path/PathScripts/PathOpGui.py +++ b/src/Mod/Path/Path/Op/Gui/Base.py @@ -22,17 +22,15 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathGeom as PathGeom -import PathScripts.PathGetPoint as PathGetPoint -import PathScripts.PathGui as PathGui -import PathScripts.PathJob as PathJob -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathSelection as PathSelection -import PathScripts.PathSetupSheet as PathSetupSheet -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Gui.GetPoint as PathGetPoint +import Path.Base.Gui.Util as PathGuiUtil +import Path.Base.SetupSheet as PathSetupSheet +import Path.Base.Util as PathUtil +import Path.Main.Job as PathJob +import Path.Op.Base as PathOp +import Path.Op.Gui.Selection as PathSelection +import PathGui import PathScripts.PathUtils as PathUtils import importlib from PySide.QtCore import QT_TRANSLATE_NOOP @@ -47,10 +45,10 @@ __doc__ = "Base classes and framework for Path operation's UI" translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ViewProvider(object): @@ -62,7 +60,7 @@ class ViewProvider(object): """ def __init__(self, vobj, resources): - PathLog.track() + Path.Log.track() self.deleteOnReject = True self.OpIcon = ":/icons/%s.svg" % resources.pixmap self.OpName = resources.name @@ -75,7 +73,7 @@ class ViewProvider(object): self.panel = None def attach(self, vobj): - PathLog.track() + Path.Log.track() self.vobj = vobj self.Object = vobj.Object self.panel = None @@ -88,17 +86,17 @@ class ViewProvider(object): edit session, if the user does not press OK, it is assumed they've changed their mind about creating the operation. """ - PathLog.track() + Path.Log.track() return hasattr(self, "deleteOnReject") and self.deleteOnReject def setDeleteObjectsOnReject(self, state=False): - PathLog.track() + Path.Log.track() self.deleteOnReject = state return self.deleteOnReject def setEdit(self, vobj=None, mode=0): """setEdit(vobj, mode=0) ... initiate editing of receivers model.""" - PathLog.track() + Path.Log.track() if 0 == mode: if vobj is None: vobj = self.vobj @@ -124,7 +122,7 @@ class ViewProvider(object): if job: job.ViewObject.Proxy.setupEditVisibility(job) else: - PathLog.info("did not find no job") + Path.Log.info("did not find no job") def clearTaskPanel(self): """clearTaskPanel() ... internal callback function when editing has finished.""" @@ -140,7 +138,7 @@ class ViewProvider(object): def __getstate__(self): """__getstate__() ... callback before receiver is saved to a file. Returns a dictionary with the receiver's resources as strings.""" - PathLog.track() + Path.Log.track() state = {} state["OpName"] = self.OpName state["OpIcon"] = self.OpIcon @@ -176,7 +174,7 @@ class ViewProvider(object): def updateData(self, obj, prop): """updateData(obj, prop) ... callback whenever a property of the receiver's model is assigned. The callback is forwarded to the task panel - in case an editing session is ongoing.""" - # PathLog.track(obj.Label, prop) # Creates a lot of noise + # Path.Log.track(obj.Label, prop) # Creates a lot of noise if self.panel: self.panel.updateData(obj, prop) @@ -185,7 +183,7 @@ class ViewProvider(object): return True def setupContextMenu(self, vobj, menu): - PathLog.track() + Path.Log.track() for action in menu.actions(): menu.removeAction(action) action = QtGui.QAction(translate("PathOp", "Edit"), menu) @@ -376,8 +374,8 @@ class TaskPanelPage(object): return def populateCombobox(self, form, enumTups, comboBoxesPropertyMap): - """populateCombobox(form, enumTups, comboBoxesPropertyMap) ... proxy for PathGui.populateCombobox()""" - PathGui.populateCombobox(form, enumTups, comboBoxesPropertyMap) + """populateCombobox(form, enumTups, comboBoxesPropertyMap) ... proxy for PathGuiUtil.populateCombobox()""" + PathGuiUtil.populateCombobox(form, enumTups, comboBoxesPropertyMap) def resetToolController(self, job, tc): if self.obj is not None: @@ -548,7 +546,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): "Please select %s from a single solid" % self.featureName(), ) FreeCAD.Console.PrintError(msg + "\n") - PathLog.debug(msg) + Path.Log.debug(msg) return False sel = selection[0] if sel.HasSubObjects: @@ -557,26 +555,26 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): and selection[0].SubObjects[0].ShapeType == "Vertex" ): if not ignoreErrors: - PathLog.error(translate("PathOp", "Vertexes are not supported")) + Path.Log.error(translate("PathOp", "Vertexes are not supported")) return False if ( not self.supportsEdges() and selection[0].SubObjects[0].ShapeType == "Edge" ): if not ignoreErrors: - PathLog.error(translate("PathOp", "Edges are not supported")) + Path.Log.error(translate("PathOp", "Edges are not supported")) return False if ( not self.supportsFaces() and selection[0].SubObjects[0].ShapeType == "Face" ): if not ignoreErrors: - PathLog.error(translate("PathOp", "Faces are not supported")) + Path.Log.error(translate("PathOp", "Faces are not supported")) return False else: if not self.supportsPanels() or "Panel" not in sel.Object.Name: if not ignoreErrors: - PathLog.error( + Path.Log.error( translate( "PathOp", "Please select %s of a solid" % self.featureName(), @@ -586,7 +584,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): return True def addBaseGeometry(self, selection): - PathLog.track(selection) + Path.Log.track(selection) if self.selectionSupportedAsBaseGeometry(selection, False): sel = selection[0] for sub in sel.SubElementNames: @@ -595,7 +593,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): return False def addBase(self): - PathLog.track() + Path.Log.track() if self.addBaseGeometry(FreeCADGui.Selection.getSelectionEx()): # self.obj.Proxy.execute(self.obj) self.setFields(self.obj) @@ -603,7 +601,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): self.updatePanelVisibility("Operation", self.obj) def deleteBase(self): - PathLog.track() + Path.Log.track() selected = self.form.baseList.selectedItems() for item in selected: self.form.baseList.takeItem(self.form.baseList.row(item)) @@ -621,7 +619,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): if sub: base = (obj, str(sub)) newlist.append(base) - PathLog.debug("Setting new base: %s -> %s" % (self.obj.Base, newlist)) + Path.Log.debug("Setting new base: %s -> %s" % (self.obj.Base, newlist)) self.obj.Base = newlist # self.obj.Proxy.execute(self.obj) @@ -677,7 +675,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): qList = self.form.baseList row = (qList.count() + qList.frameWidth()) * 15 # qList.setMinimumHeight(row) - PathLog.debug( + Path.Log.debug( "baseList({}, {}) {} * {}".format( qList.size(), row, qList.count(), qList.sizeHintForRow(0) ) @@ -748,7 +746,7 @@ class TaskPanelBaseLocationPage(TaskPanelPage): FreeCAD.ActiveDocument.recompute() def updateLocations(self): - PathLog.track() + Path.Log.track() locations = [] for i in range(self.formLoc.baseList.rowCount()): x = self.formLoc.baseList.item(i, 0).data(self.DataLocation) @@ -824,10 +822,10 @@ class TaskPanelHeightsPage(TaskPanelPage): return FreeCADGui.PySideUic.loadUi(":/panels/PageHeightsEdit.ui") def initPage(self, obj): - self.safeHeight = PathGui.QuantitySpinBox( + self.safeHeight = PathGuiUtil.QuantitySpinBox( self.form.safeHeight, obj, "SafeHeight" ) - self.clearanceHeight = PathGui.QuantitySpinBox( + self.clearanceHeight = PathGuiUtil.QuantitySpinBox( self.form.clearanceHeight, obj, "ClearanceHeight" ) @@ -892,7 +890,7 @@ class TaskPanelDepthsPage(TaskPanelPage): def initPage(self, obj): if self.haveStartDepth(): - self.startDepth = PathGui.QuantitySpinBox( + self.startDepth = PathGuiUtil.QuantitySpinBox( self.form.startDepth, obj, "StartDepth" ) else: @@ -901,7 +899,7 @@ class TaskPanelDepthsPage(TaskPanelPage): self.form.startDepthSet.hide() if self.haveFinalDepth(): - self.finalDepth = PathGui.QuantitySpinBox( + self.finalDepth = PathGuiUtil.QuantitySpinBox( self.form.finalDepth, obj, "FinalDepth" ) else: @@ -919,13 +917,13 @@ class TaskPanelDepthsPage(TaskPanelPage): self.form.finalDepthSet.hide() if self.haveStepDown(): - self.stepDown = PathGui.QuantitySpinBox(self.form.stepDown, obj, "StepDown") + self.stepDown = PathGuiUtil.QuantitySpinBox(self.form.stepDown, obj, "StepDown") else: self.form.stepDown.hide() self.form.stepDownLabel.hide() if self.haveFinishDepth(): - self.finishDepth = PathGui.QuantitySpinBox( + self.finishDepth = PathGuiUtil.QuantitySpinBox( self.form.finishDepth, obj, "FinishDepth" ) else: @@ -985,7 +983,7 @@ class TaskPanelDepthsPage(TaskPanelPage): def depthSet(self, obj, spinbox, prop): z = self.selectionZLevel(FreeCADGui.Selection.getSelectionEx()) if z is not None: - PathLog.debug("depthSet(%s, %s, %.2f)" % (obj.Label, prop, z)) + Path.Log.debug("depthSet(%s, %s, %.2f)" % (obj.Label, prop, z)) if spinbox.expression(): obj.setExpression(prop, None) self.setDirty() @@ -993,14 +991,14 @@ class TaskPanelDepthsPage(TaskPanelPage): if spinbox.updateProperty(): self.setDirty() else: - PathLog.info("depthSet(-)") + Path.Log.info("depthSet(-)") def selectionZLevel(self, sel): if len(sel) == 1 and len(sel[0].SubObjects) == 1: sub = sel[0].SubObjects[0] if "Vertex" == sub.ShapeType: return sub.Z - if PathGeom.isHorizontal(sub): + if Path.Geom.isHorizontal(sub): if "Edge" == sub.ShapeType: return sub.Vertexes[0].Z if "Face" == sub.ShapeType: @@ -1030,10 +1028,10 @@ class TaskPanelDiametersPage(TaskPanelPage): return FreeCADGui.PySideUic.loadUi(":/panels/PageDiametersEdit.ui") def initPage(self, obj): - self.minDiameter = PathGui.QuantitySpinBox( + self.minDiameter = PathGuiUtil.QuantitySpinBox( self.form.minDiameter, obj, "MinDiameter" ) - self.maxDiameter = PathGui.QuantitySpinBox( + self.maxDiameter = PathGuiUtil.QuantitySpinBox( self.form.maxDiameter, obj, "MaxDiameter" ) @@ -1071,7 +1069,7 @@ class TaskPanel(object): """ def __init__(self, obj, deleteOnReject, opPage, selectionFactory): - PathLog.track(obj.Label, deleteOnReject, opPage, selectionFactory) + Path.Log.track(obj.Label, deleteOnReject, opPage, selectionFactory) FreeCAD.ActiveDocument.openTransaction(translate("PathOp", "AreaOp Operation")) self.obj = obj self.deleteOnReject = deleteOnReject @@ -1133,7 +1131,7 @@ class TaskPanel(object): page.initPage(obj) page.onDirtyChanged(self.pageDirtyChanged) - taskPanelLayout = PathPreferences.defaultTaskPanelLayout() + taskPanelLayout = Path.Preferences.defaultTaskPanelLayout() if taskPanelLayout < 2: opTitle = opPage.getTitle(obj) @@ -1209,7 +1207,7 @@ class TaskPanel(object): PathUtil.clearExpressionEngine(self.obj) FreeCAD.ActiveDocument.removeObject(self.obj.Name) except Exception as ee: - PathLog.debug("{}\n".format(ee)) + Path.Log.debug("{}\n".format(ee)) FreeCAD.ActiveDocument.commitTransaction() self.cleanup(resetEdit) return True @@ -1250,20 +1248,20 @@ class TaskPanel(object): def panelGetFields(self): """panelGetFields() ... invoked to trigger a complete transfer of UI data to the model.""" - PathLog.track() + Path.Log.track() for page in self.featurePages: page.pageGetFields() def panelSetFields(self): """panelSetFields() ... invoked to trigger a complete transfer of the model's properties to the UI.""" - PathLog.track() + Path.Log.track() self.obj.Proxy.sanitizeBase(self.obj) for page in self.featurePages: page.pageSetFields() def panelCleanup(self): """panelCleanup() ... invoked before the receiver is destroyed.""" - PathLog.track() + Path.Log.track() for page in self.featurePages: page.pageCleanup() @@ -1282,7 +1280,7 @@ class TaskPanel(object): def setupUi(self): """setupUi() ... internal function to initialise all pages.""" - PathLog.track(self.deleteOnReject) + Path.Log.track(self.deleteOnReject) if ( self.deleteOnReject @@ -1311,7 +1309,7 @@ class TaskPanel(object): def updateData(self, obj, prop): """updateDate(obj, prop) ... callback invoked whenever a model's property is assigned a value.""" - # PathLog.track(obj.Label, prop) # creates a lot of noise + # Path.Log.track(obj.Label, prop) # creates a lot of noise for page in self.featurePages: page.pageUpdateData(obj, prop) @@ -1391,7 +1389,7 @@ def Create(res): diag.setWindowModality(QtCore.Qt.ApplicationModal) diag.exec_() except PathOp.PathNoTCException: - PathLog.warning(translate("PathOp", "No tool controller, aborting op creation")) + Path.Log.warning(translate("PathOp", "No tool controller, aborting op creation")) FreeCAD.ActiveDocument.abortTransaction() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Path/PathScripts/PathCircularHoleBaseGui.py b/src/Mod/Path/Path/Op/Gui/CircularHoleBase.py similarity index 92% rename from src/Mod/Path/PathScripts/PathCircularHoleBaseGui.py rename to src/Mod/Path/Path/Op/Gui/CircularHoleBase.py index 4f75193f31..cbd4e5eb7e 100644 --- a/src/Mod/Path/PathScripts/PathCircularHoleBaseGui.py +++ b/src/Mod/Path/Path/Op/Gui/CircularHoleBase.py @@ -22,9 +22,9 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui +import Path +import Path.Op.Gui.Base as PathOpGui +import PathGui from PySide import QtCore, QtGui @@ -36,10 +36,10 @@ __doc__ = "Implementation of circular hole specific base geometry page controlle LOGLEVEL = False if LOGLEVEL: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.NOTICE, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.NOTICE, Path.Log.thisModule()) class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): @@ -63,7 +63,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): def setFields(self, obj): """setFields(obj) ... fill form with values from obj""" - PathLog.track() + Path.Log.track() self.form.baseList.blockSignals(True) self.form.baseList.clearContents() self.form.baseList.setRowCount(0) @@ -98,7 +98,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): def itemActivated(self): """itemActivated() ... callback when item in table is selected""" - PathLog.track() + Path.Log.track() if self.form.baseList.selectedItems(): self.form.deleteBase.setEnabled(True) FreeCADGui.Selection.clearSelection() @@ -109,7 +109,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): activatedRows.append(row) obj = item.data(self.DataObject) sub = str(item.data(self.DataObjectSub)) - PathLog.debug("itemActivated() -> %s.%s" % (obj.Label, sub)) + Path.Log.debug("itemActivated() -> %s.%s" % (obj.Label, sub)) if sub: FreeCADGui.Selection.addSelection(obj, sub) else: @@ -119,7 +119,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): def deleteBase(self): """deleteBase() ... callback for push button""" - PathLog.track() + Path.Log.track() selected = [ self.form.baseList.row(item) for item in self.form.baseList.selectedItems() ] @@ -135,23 +135,23 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): def updateBase(self): """updateBase() ... helper function to transfer current table to obj""" - PathLog.track() + Path.Log.track() newlist = [] for i in range(self.form.baseList.rowCount()): item = self.form.baseList.item(i, 0) obj = item.data(self.DataObject) sub = str(item.data(self.DataObjectSub)) base = (obj, sub) - PathLog.debug("keeping (%s.%s)" % (obj.Label, sub)) + Path.Log.debug("keeping (%s.%s)" % (obj.Label, sub)) newlist.append(base) - PathLog.debug("obj.Base=%s newlist=%s" % (self.obj.Base, newlist)) + Path.Log.debug("obj.Base=%s newlist=%s" % (self.obj.Base, newlist)) self.updating = True self.obj.Base = newlist self.updating = False def checkedChanged(self): """checkeChanged() ... callback when checked status of a base feature changed""" - PathLog.track() + Path.Log.track() disabled = [] for i in range(0, self.form.baseList.rowCount()): item = self.form.baseList.item(i, 0) diff --git a/src/Mod/Path/PathScripts/PathComment.py b/src/Mod/Path/Path/Op/Gui/Comment.py similarity index 96% rename from src/Mod/Path/PathScripts/PathComment.py rename to src/Mod/Path/Path/Op/Gui/Comment.py index 1f5e7c06ce..a359347892 100644 --- a/src/Mod/Path/PathScripts/PathComment.py +++ b/src/Mod/Path/Path/Op/Gui/Comment.py @@ -115,14 +115,14 @@ class CommandPathComment: def Activated(self): FreeCAD.ActiveDocument.openTransaction("Create a Comment in your CNC program") - FreeCADGui.addModule("PathScripts.PathComment") + FreeCADGui.addModule("Path.Op.Gui.Comment") snippet = """ import Path import PathScripts from PathScripts import PathUtils obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Comment") -PathScripts.PathComment.Comment(obj) -PathScripts.PathComment._ViewProviderComment(obj.ViewObject) +Path.Op.Gui.Comment.Comment(obj) +Path.Op.Gui.Comment._ViewProviderComment(obj.ViewObject) PathUtils.addToJob(obj) """ diff --git a/src/Mod/Path/PathScripts/PathCopy.py b/src/Mod/Path/Path/Op/Gui/Copy.py similarity index 95% rename from src/Mod/Path/PathScripts/PathCopy.py rename to src/Mod/Path/Path/Op/Gui/Copy.py index 0a622a3331..939da3c488 100644 --- a/src/Mod/Path/PathScripts/PathCopy.py +++ b/src/Mod/Path/Path/Op/Gui/Copy.py @@ -104,12 +104,11 @@ class CommandPathCopy: def Activated(self): FreeCAD.ActiveDocument.openTransaction("Create Copy") - FreeCADGui.addModule("PathScripts.PathCopy") + FreeCADGui.addModule("Path.Op.Gui.Copy") consolecode = """ import Path -import PathScripts -from PathScripts import PathCopy +import Path.Op.Gui.Copy selGood = True # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelection() @@ -125,8 +124,8 @@ if not selection[0].isDerivedFrom("Path::Feature"): if selGood: obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", str(selection[0].Name)+'_Copy') - PathScripts.PathCopy.ObjectPathCopy(obj) - PathScripts.PathCopy.ViewProviderPathCopy(obj.ViewObject) + Path.Op.Gui.Copy.ObjectPathCopy(obj) + Path.Op.Gui.Copy.ViewProviderPathCopy(obj.ViewObject) obj.Base = FreeCAD.ActiveDocument.getObject(selection[0].Name) if hasattr(obj.Base, 'ToolController'): obj.ToolController = obj.Base.ToolController diff --git a/src/Mod/Path/PathScripts/PathCustomGui.py b/src/Mod/Path/Path/Op/Gui/Custom.py similarity index 97% rename from src/Mod/Path/PathScripts/PathCustomGui.py rename to src/Mod/Path/Path/Op/Gui/Custom.py index 184229247d..4b00ad7d51 100644 --- a/src/Mod/Path/PathScripts/PathCustomGui.py +++ b/src/Mod/Path/Path/Op/Gui/Custom.py @@ -22,8 +22,8 @@ import FreeCAD import FreeCADGui -import PathScripts.PathCustom as PathCustom -import PathScripts.PathOpGui as PathOpGui +import Path.Op.Custom as PathCustom +import Path.Op.Gui.Base as PathOpGui from PySide.QtCore import QT_TRANSLATE_NOOP diff --git a/src/Mod/Path/PathScripts/PathDeburrGui.py b/src/Mod/Path/Path/Op/Gui/Deburr.py similarity index 90% rename from src/Mod/Path/PathScripts/PathDeburrGui.py rename to src/Mod/Path/Path/Op/Gui/Deburr.py index 2222721d2a..64ceb850dc 100644 --- a/src/Mod/Path/PathScripts/PathDeburrGui.py +++ b/src/Mod/Path/Path/Op/Gui/Deburr.py @@ -22,10 +22,10 @@ import FreeCAD import FreeCADGui -import PathScripts.PathDeburr as PathDeburr -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Deburr as PathDeburr +import Path.Op.Gui.Base as PathOpGui from PySide import QtCore, QtGui from PySide.QtCore import QT_TRANSLATE_NOOP @@ -36,10 +36,10 @@ __doc__ = "Deburr operation page controller and command implementation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -83,8 +83,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.joinRound.setIcon(iconRound) def getFields(self, obj): - PathGui.updateInputField(obj, "Width", self.form.value_W) - PathGui.updateInputField(obj, "ExtraDepth", self.form.value_h) + PathGuiUtil.updateInputField(obj, "Width", self.form.value_W) + PathGuiUtil.updateInputField(obj, "ExtraDepth", self.form.value_h) if self.form.joinRound.isChecked(): obj.Join = "Round" elif self.form.joinMiter.isChecked(): @@ -113,10 +113,10 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.selectInComboBox(obj.Direction, self.form.direction) def updateWidth(self): - PathGui.updateInputField(self.obj, "Width", self.form.value_W) + PathGuiUtil.updateInputField(self.obj, "Width", self.form.value_W) def updateExtraDepth(self): - PathGui.updateInputField(self.obj, "ExtraDepth", self.form.value_h) + PathGuiUtil.updateInputField(self.obj, "ExtraDepth", self.form.value_h) def getSignalsForUpdate(self, obj): signals = [] diff --git a/src/Mod/Path/PathScripts/PathDrillingGui.py b/src/Mod/Path/Path/Op/Gui/Drilling.py similarity index 91% rename from src/Mod/Path/PathScripts/PathDrillingGui.py rename to src/Mod/Path/Path/Op/Gui/Drilling.py index 64c093c66e..67b7a3b0d8 100644 --- a/src/Mod/Path/PathScripts/PathDrillingGui.py +++ b/src/Mod/Path/Path/Op/Gui/Drilling.py @@ -22,12 +22,12 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui -import PathScripts.PathDrilling as PathDrilling -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Drilling as PathDrilling +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Gui.CircularHoleBase as PathCircularHoleBaseGui +import PathGui from PySide import QtCore @@ -38,23 +38,23 @@ __doc__ = "UI and Command for Path Drilling Operation." __contributors__ = "IMBack!" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): """Controller for the drilling operation's page""" def initPage(self, obj): - self.peckDepthSpinBox = PathGui.QuantitySpinBox( + self.peckDepthSpinBox = PathGuiUtil.QuantitySpinBox( self.form.peckDepth, obj, "PeckDepth" ) - self.peckRetractSpinBox = PathGui.QuantitySpinBox( + self.peckRetractSpinBox = PathGuiUtil.QuantitySpinBox( self.form.peckRetractHeight, obj, "RetractHeight" ) - self.dwellTimeSpinBox = PathGui.QuantitySpinBox( + self.dwellTimeSpinBox = PathGuiUtil.QuantitySpinBox( self.form.dwellTime, obj, "DwellTime" ) self.form.chipBreakEnabled.setEnabled(False) @@ -105,7 +105,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): def getFields(self, obj): """setFields(obj) ... update obj's properties with values from the UI""" - PathLog.track() + Path.Log.track() self.peckDepthSpinBox.updateProperty() self.peckRetractSpinBox.updateProperty() self.dwellTimeSpinBox.updateProperty() @@ -124,7 +124,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): def setFields(self, obj): """setFields(obj) ... update UI with obj properties' values""" - PathLog.track() + Path.Log.track() self.updateQuantitySpinBoxes() if obj.DwellEnabled: diff --git a/src/Mod/Path/PathScripts/PathEngraveGui.py b/src/Mod/Path/Path/Op/Gui/Engrave.py similarity index 92% rename from src/Mod/Path/PathScripts/PathEngraveGui.py rename to src/Mod/Path/Path/Op/Gui/Engrave.py index d90064e009..3ea572574e 100644 --- a/src/Mod/Path/PathScripts/PathEngraveGui.py +++ b/src/Mod/Path/Path/Op/Gui/Engrave.py @@ -22,10 +22,10 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathEngrave as PathEngrave -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui +import Path +import Path.Op.Engrave as PathEngrave +import Path.Op.Gui.Base as PathOpGui +import PathGui import PathScripts.PathUtils as PathUtils from PySide import QtCore, QtGui @@ -37,10 +37,10 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Engrave operation page controller and command implementation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -70,7 +70,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): job = PathUtils.findParentJob(self.obj) base = job.Proxy.resourceClone(job, sel.Object) if not base: - PathLog.notice( + Path.Log.notice( ( translate("Path", "%s is not a Base Model object of the job %s") + "\n" @@ -79,7 +79,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): ) continue if base in shapes: - PathLog.notice( + Path.Log.notice( (translate("Path", "Base shape %s already in the list") + "\n") % (sel.Object.Label) ) @@ -89,7 +89,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): # selectively add some elements of the drawing to the Base for sub in sel.SubElementNames: if "Vertex" in sub: - PathLog.info("Ignoring vertex") + Path.Log.info("Ignoring vertex") else: self.obj.Proxy.addBase(self.obj, base, sub) else: @@ -116,7 +116,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): self.form.baseList.blockSignals(False) def updateBase(self): - PathLog.track() + Path.Log.track() shapes = [] for i in range(self.form.baseList.count()): item = self.form.baseList.item(i) @@ -124,7 +124,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): sub = item.data(self.super().DataObjectSub) if not sub: shapes.append(obj) - PathLog.debug( + Path.Log.debug( "Setting new base shapes: %s -> %s" % (self.obj.BaseShapes, shapes) ) self.obj.BaseShapes = shapes diff --git a/src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py b/src/Mod/Path/Path/Op/Gui/FeatureExtension.py similarity index 91% rename from src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py rename to src/Mod/Path/Path/Op/Gui/FeatureExtension.py index b133c80aff..8ce59b0260 100644 --- a/src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py +++ b/src/Mod/Path/Path/Op/Gui/FeatureExtension.py @@ -24,11 +24,10 @@ from PySide import QtCore, QtGui from pivy import coin import FreeCAD import FreeCADGui -import PathScripts.PathFeatureExtensions as FeatureExtensions -import PathScripts.PathGeom as PathGeom -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.FeatureExtension as FeatureExtensions +import Path.Op.Gui.Base as PathOpGui # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -44,10 +43,10 @@ __doc__ = "Extensions feature page controller." translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class _Extension(object): @@ -198,7 +197,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.extensions = list() - self.defaultLength = PathGui.QuantitySpinBox( + self.defaultLength = PathGuiUtil.QuantitySpinBox( self.form.defaultLength, obj, "ExtensionLengthDefault" ) @@ -229,7 +228,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): try: self.obj.ViewObject.RootNode.removeChild(self.switch) except ReferenceError: - PathLog.debug("obj already destroyed - no cleanup required") + Path.Log.debug("obj already destroyed - no cleanup required") def getForm(self): form = FreeCADGui.PySideUic.loadUi(":/panels/PageOpPocketExtEdit.ui") @@ -246,7 +245,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): cb(item, ext) def currentExtensions(self): - PathLog.debug("currentExtensions()") + Path.Log.debug("currentExtensions()") extensions = [] def extractExtension(item, ext): @@ -255,16 +254,16 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): if self.form.enableExtensions.isChecked(): self.forAllItemsCall(extractExtension) - PathLog.track("extensions", extensions) + Path.Log.track("extensions", extensions) return extensions def updateProxyExtensions(self, obj): - PathLog.debug("updateProxyExtensions()") + Path.Log.debug("updateProxyExtensions()") self.extensions = self.currentExtensions() FeatureExtensions.setExtensions(obj, self.extensions) def getFields(self, obj): - PathLog.track(obj.Label, self.model.rowCount(), self.model.columnCount()) + Path.Log.track(obj.Label, self.model.rowCount(), self.model.columnCount()) self.blockUpdateData = True if obj.ExtensionCorners != self.form.extendCorners.isChecked(): @@ -275,8 +274,8 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.blockUpdateData = False def setFields(self, obj): - PathLog.track(obj.Label) - # PathLog.debug("setFields()") + Path.Log.track(obj.Label) + # Path.Log.debug("setFields()") if obj.ExtensionCorners != self.form.extendCorners.isChecked(): self.form.extendCorners.toggle() @@ -312,10 +311,10 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self._enableExtensions() # Recalculate extensions def createItemForBaseModel(self, base, sub, edges, extensions): - PathLog.track( + Path.Log.track( base.Label, sub, "+", len(edges), len(base.Shape.getElement(sub).Edges) ) - # PathLog.debug("createItemForBaseModel() label: {}, sub: {}, {}, edgeCnt: {}, subEdges: {}".format(base.Label, sub, '+', len(edges), len(base.Shape.getElement(sub).Edges))) + # Path.Log.debug("createItemForBaseModel() label: {}, sub: {}, {}, edgeCnt: {}, subEdges: {}".format(base.Label, sub, '+', len(edges), len(base.Shape.getElement(sub).Edges))) extendCorners = self.form.extendCorners.isChecked() subShape = base.Shape.getElement(sub) @@ -361,16 +360,16 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): if extendCorners: def edgesMatchShape(e0, e1): - flipped = PathGeom.flipEdge(e1) + flipped = Path.Geom.flipEdge(e1) if flipped: - return PathGeom.edgesMatch(e0, e1) or PathGeom.edgesMatch( + return Path.Geom.edgesMatch(e0, e1) or Path.Geom.edgesMatch( e0, flipped ) else: - return PathGeom.edgesMatch(e0, e1) + return Path.Geom.edgesMatch(e0, e1) self.extensionEdges = extensionEdges - PathLog.debug("extensionEdges.values(): {}".format(extensionEdges.values())) + Path.Log.debug("extensionEdges.values(): {}".format(extensionEdges.values())) for edgeList in Part.sortEdges( list(extensionEdges.keys()) ): # Identify connected edges that form wires @@ -402,11 +401,11 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): return item def setExtensions(self, extensions): - PathLog.track(len(extensions)) - PathLog.debug("setExtensions()") + Path.Log.track(len(extensions)) + Path.Log.debug("setExtensions()") if self.extensionsReady: - PathLog.debug("setExtensions() returning per `extensionsReady` flag") + Path.Log.debug("setExtensions() returning per `extensionsReady` flag") return self.form.extensionTree.blockSignals(True) @@ -482,11 +481,11 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.form.extensionTree.blockSignals(False) self.extensionsReady = True - PathLog.debug(" setExtensions() finished and setting `extensionsReady=True`") + Path.Log.debug(" setExtensions() finished and setting `extensionsReady=True`") def updateData(self, obj, prop): - PathLog.track(obj.Label, prop, self.blockUpdateData) - # PathLog.debug("updateData({})".format(prop)) + Path.Log.track(obj.Label, prop, self.blockUpdateData) + # Path.Log.debug("updateData({})".format(prop)) if not self.blockUpdateData: if self.fieldsSet: @@ -503,10 +502,10 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.extensionsReady = False def restoreSelection(self, selection): - PathLog.debug("restoreSelection()") - PathLog.track() + Path.Log.debug("restoreSelection()") + Path.Log.track() if 0 == self.model.rowCount(): - PathLog.track("-") + Path.Log.track("-") self.form.buttonClear.setEnabled(False) self.form.buttonDisable.setEnabled(False) self.form.buttonEnable.setEnabled(False) @@ -549,11 +548,11 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.forAllItemsCall(setSelectionVisuals) def selectionChanged(self): - PathLog.debug("selectionChanged()") + Path.Log.debug("selectionChanged()") self.restoreSelection([]) def extensionsClear(self): - PathLog.debug("extensionsClear()") + Path.Log.debug("extensionsClear()") def disableItem(item, ext): item.setCheckState(QtCore.Qt.Unchecked) @@ -563,8 +562,8 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.setDirty() def _extensionsSetState(self, state): - PathLog.debug("_extensionsSetState()") - PathLog.track(state) + Path.Log.debug("_extensionsSetState()") + Path.Log.track(state) for index in self.selectionModel.selectedIndexes(): item = self.model.itemFromIndex(index) ext = item.data(self.DataObject) @@ -580,7 +579,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self._extensionsSetState(QtCore.Qt.Checked) def updateItemEnabled(self, item): - PathLog.track(item) + Path.Log.track(item) ext = item.data(self.DataObject) if item.checkState() == QtCore.Qt.Checked: ext.enable() @@ -606,8 +605,8 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): # self.setDirty() def toggleExtensionCorners(self): - PathLog.debug("toggleExtensionCorners()") - PathLog.track() + Path.Log.debug("toggleExtensionCorners()") + Path.Log.track() self.extensionsReady = False extensions = FeatureExtensions.getExtensions(self.obj) self.setExtensions(extensions) @@ -615,7 +614,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.setDirty() def getSignalsForUpdate(self, obj): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) signals = [] signals.append(self.form.defaultLength.editingFinished) signals.append(self.form.enableExtensions.toggled) @@ -654,7 +653,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): if page.panelTitle == "Operation" and hasattr( page.form, "useOutline" ): - PathLog.debug("Found useOutline checkbox") + Path.Log.debug("Found useOutline checkbox") self.useOutlineCheckbox = page.form.useOutline if page.form.useOutline.isChecked(): self.useOutline = 1 @@ -682,7 +681,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): if self.form.enableExtensions.isChecked(): enabled = True - PathLog.debug("_autoEnableExtensions() is {}".format(enabled)) + Path.Log.debug("_autoEnableExtensions() is {}".format(enabled)) self.enabled = enabled def _enableExtensions(self): @@ -691,7 +690,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): This method manages the enabled or disabled state of the extensionsEdit Task Panel input group. """ - PathLog.debug("_enableExtensions()") + Path.Log.debug("_enableExtensions()") if self.form.enableExtensions.isChecked(): self.enabled = True @@ -709,7 +708,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): This method manages the state of the button and the message thereof. """ self._getUseOutlineState() # Find `useOutline` checkbox and get its boolean value - PathLog.debug("_includeEdgesAndWires()") + Path.Log.debug("_includeEdgesAndWires()") self.extensionsReady = False self._enableExtensions() @@ -725,16 +724,16 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): cacheLabel = base.Name + "_" + sub + "_None" if cacheLabel in self.extensionsCache.keys(): - # PathLog.debug("return _cachedExtension({})".format(cacheLabel)) + # Path.Log.debug("return _cachedExtension({})".format(cacheLabel)) return self.extensionsCache[cacheLabel] else: - # PathLog.debug("_cachedExtension({}) created".format(cacheLabel)) + # Path.Log.debug("_cachedExtension({}) created".format(cacheLabel)) _ext = _Extension(obj, base, sub, label) self.extensionsCache[cacheLabel] = _ext # cache the extension return _ext def _resetCachedExtensions(self): - PathLog.debug("_resetCachedExtensions()") + Path.Log.debug("_resetCachedExtensions()") reset = dict() self.extensionsCache = reset self.extensionsReady = False diff --git a/src/Mod/Path/PathScripts/PathHelixGui.py b/src/Mod/Path/Path/Op/Gui/Helix.py similarity index 88% rename from src/Mod/Path/PathScripts/PathHelixGui.py rename to src/Mod/Path/Path/Op/Gui/Helix.py index 4ea069ed1e..2a86d1ae23 100644 --- a/src/Mod/Path/PathScripts/PathHelixGui.py +++ b/src/Mod/Path/Path/Op/Gui/Helix.py @@ -22,12 +22,12 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui -import PathScripts.PathHelix as PathHelix -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathGui as PathGui +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Gui.CircularHoleBase as PathCircularHoleBaseGui +import Path.Op.Helix as PathHelix +import PathGui from PySide.QtCore import QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate @@ -39,10 +39,10 @@ __doc__ = "Helix operation page controller and command implementation." LOGLEVEL = False if LOGLEVEL: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.NOTICE, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.NOTICE, Path.Log.thisModule()) class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): @@ -61,21 +61,21 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): def getFields(self, obj): """getFields(obj) ... transfers values from UI to obj's proprties""" - PathLog.track() + Path.Log.track() if obj.Direction != str(self.form.direction.currentData()): obj.Direction = str(self.form.direction.currentData()) if obj.StartSide != str(self.form.startSide.currentData()): obj.StartSide = str(self.form.startSide.currentData()) if obj.StepOver != self.form.stepOverPercent.value(): obj.StepOver = self.form.stepOverPercent.value() - PathGui.updateInputField(obj, "OffsetExtra", self.form.extraOffset) + PathGuiUtil.updateInputField(obj, "OffsetExtra", self.form.extraOffset) self.updateToolController(obj, self.form.toolController) self.updateCoolant(obj, self.form.coolantController) def setFields(self, obj): """setFields(obj) ... transfers obj's property values to UI""" - PathLog.track() + Path.Log.track() self.form.stepOverPercent.setValue(obj.StepOver) self.selectInComboBox(obj.Direction, self.form.direction) diff --git a/src/Mod/Path/PathScripts/PathHop.py b/src/Mod/Path/Path/Op/Gui/Hop.py similarity index 96% rename from src/Mod/Path/PathScripts/PathHop.py rename to src/Mod/Path/Path/Op/Gui/Hop.py index 1447f98fa3..d3b2a04f32 100644 --- a/src/Mod/Path/PathScripts/PathHop.py +++ b/src/Mod/Path/Path/Op/Gui/Hop.py @@ -125,13 +125,13 @@ class CommandPathHop: return FreeCAD.ActiveDocument.openTransaction("Create Hop") - FreeCADGui.addModule("PathScripts.PathHop") + FreeCADGui.addModule("Path.Op.Gui.Hop") 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)") + FreeCADGui.doCommand("Path.Op.Gui.Hop.ObjectHop(obj)") + FreeCADGui.doCommand("Path.Op.Gui.Hop.ViewProviderPathHop(obj.ViewObject)") FreeCADGui.doCommand( "obj.NextObject = FreeCAD.ActiveDocument." + selection[0].Name ) diff --git a/src/Mod/Path/PathScripts/PathMillFaceGui.py b/src/Mod/Path/Path/Op/Gui/MillFace.py similarity index 87% rename from src/Mod/Path/PathScripts/PathMillFaceGui.py rename to src/Mod/Path/Path/Op/Gui/MillFace.py index 7ed8c37593..ae264e49d4 100644 --- a/src/Mod/Path/PathScripts/PathMillFaceGui.py +++ b/src/Mod/Path/Path/Op/Gui/MillFace.py @@ -22,11 +22,11 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathMillFace as PathMillFace -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathPocketBaseGui as PathPocketBaseGui -import PathScripts.PathPocketShape as PathPocketShape +import Path +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Gui.PocketBase as PathPocketBaseGui +import Path.Op.MillFace as PathMillFace +import Path.Op.PocketShape as PathPocketShape import FreeCADGui __title__ = "Path Face Mill Operation UI" @@ -35,17 +35,17 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Face Mill operation page controller and command implementation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class TaskPanelOpPage(PathPocketBaseGui.TaskPanelOpPage): """Page controller class for the face milling operation.""" def getForm(self): - PathLog.track() + Path.Log.track() """getForm() ... return UI""" form = FreeCADGui.PySideUic.loadUi(":/panels/PageOpPocketFullEdit.ui") diff --git a/src/Mod/Path/PathScripts/PathPocketGui.py b/src/Mod/Path/Path/Op/Gui/Pocket.py similarity index 87% rename from src/Mod/Path/PathScripts/PathPocketGui.py rename to src/Mod/Path/Path/Op/Gui/Pocket.py index 80b20ef9ab..d733bcb3a7 100644 --- a/src/Mod/Path/PathScripts/PathPocketGui.py +++ b/src/Mod/Path/Path/Op/Gui/Pocket.py @@ -21,18 +21,18 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathPocket as PathPocket -import PathScripts.PathPocketBaseGui as PathPocketBaseGui -import PathScripts.PathLog as PathLog +import Path +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Gui.PocketBase as PathPocketBaseGui +import Path.Op.Pocket as PathPocket from PySide.QtCore import QT_TRANSLATE_NOOP if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) __title__ = "Path Pocket Operation UI" diff --git a/src/Mod/Path/PathScripts/PathPocketBaseGui.py b/src/Mod/Path/Path/Op/Gui/PocketBase.py similarity index 93% rename from src/Mod/Path/PathScripts/PathPocketBaseGui.py rename to src/Mod/Path/Path/Op/Gui/PocketBase.py index 37d477a1de..f0552f0e1a 100644 --- a/src/Mod/Path/PathScripts/PathPocketBaseGui.py +++ b/src/Mod/Path/Path/Op/Gui/PocketBase.py @@ -22,11 +22,11 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathGui as PathGui -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathPocket as PathPocket -import PathScripts.PathLog as PathLog +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Pocket as PathPocket +import PathGui __title__ = "Path Pocket Base Operation UI" __author__ = "sliptonic (Brad Collette)" @@ -34,10 +34,10 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Base page controller and command implementation for path pocket operations." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -112,7 +112,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.zigZagAngle.setEnabled(True) if setModel: - PathGui.updateInputField(obj, "ZigZagAngle", self.form.zigZagAngle) + PathGuiUtil.updateInputField(obj, "ZigZagAngle", self.form.zigZagAngle) def getFields(self, obj): """getFields(obj) ... transfers values from UI to obj's proprties""" @@ -123,7 +123,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if obj.OffsetPattern != str(self.form.offsetPattern.currentData()): obj.OffsetPattern = str(self.form.offsetPattern.currentData()) - PathGui.updateInputField(obj, "ExtraOffset", self.form.extraOffset) + PathGuiUtil.updateInputField(obj, "ExtraOffset", self.form.extraOffset) self.updateToolController(obj, self.form.toolController) self.updateCoolant(obj, self.form.coolantController) self.updateZigZagAngle(obj) diff --git a/src/Mod/Path/PathScripts/PathPocketShapeGui.py b/src/Mod/Path/Path/Op/Gui/PocketShape.py similarity index 87% rename from src/Mod/Path/PathScripts/PathPocketShapeGui.py rename to src/Mod/Path/Path/Op/Gui/PocketShape.py index dd88dadaf8..00f699b61d 100644 --- a/src/Mod/Path/PathScripts/PathPocketShapeGui.py +++ b/src/Mod/Path/Path/Op/Gui/PocketShape.py @@ -21,11 +21,11 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathPocketShape as PathPocketShape -import PathScripts.PathPocketBaseGui as PathPocketBaseGui -import PathScripts.PathFeatureExtensionsGui as PathFeatureExtensionsGui +import Path +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Gui.FeatureExtension as PathFeatureExtensionsGui +import Path.Op.Gui.PocketBase as PathPocketBaseGui +import Path.Op.PocketShape as PathPocketShape from PySide.QtCore import QT_TRANSLATE_NOOP # lazily loaded modules @@ -39,10 +39,10 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Pocket Shape operation page controller and command implementation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate diff --git a/src/Mod/Path/PathScripts/PathProbeGui.py b/src/Mod/Path/Path/Op/Gui/Probe.py similarity index 89% rename from src/Mod/Path/PathScripts/PathProbeGui.py rename to src/Mod/Path/Path/Op/Gui/Probe.py index 96c80b50ae..fc9fc0076f 100644 --- a/src/Mod/Path/PathScripts/PathProbeGui.py +++ b/src/Mod/Path/Path/Op/Gui/Probe.py @@ -22,11 +22,11 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathProbe as PathProbe -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Probe as PathProbe +import PathGui from PySide.QtCore import QT_TRANSLATE_NOOP from PySide import QtCore, QtGui @@ -38,10 +38,10 @@ __doc__ = "Probing operation page controller and command implementation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -56,8 +56,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): def getFields(self, obj): """getFields(obj) ... transfers values from UI to obj's proprties""" self.updateToolController(obj, self.form.toolController) - PathGui.updateInputField(obj, "Xoffset", self.form.Xoffset) - PathGui.updateInputField(obj, "Yoffset", self.form.Yoffset) + PathGuiUtil.updateInputField(obj, "Xoffset", self.form.Xoffset) + PathGuiUtil.updateInputField(obj, "Yoffset", self.form.Yoffset) obj.PointCountX = self.form.PointCountX.value() obj.PointCountY = self.form.PointCountY.value() obj.OutputFileName = str(self.form.OutputFileName.text()) diff --git a/src/Mod/Path/PathScripts/PathProfileGui.py b/src/Mod/Path/Path/Op/Gui/Profile.py similarity index 95% rename from src/Mod/Path/PathScripts/PathProfileGui.py rename to src/Mod/Path/Path/Op/Gui/Profile.py index 0a5513d61a..0ffede83d8 100644 --- a/src/Mod/Path/PathScripts/PathProfileGui.py +++ b/src/Mod/Path/Path/Op/Gui/Profile.py @@ -22,10 +22,10 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathGui as PathGui -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathProfile as PathProfile +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Profile as PathProfile +import PathGui from PySide.QtCore import QT_TRANSLATE_NOOP @@ -76,7 +76,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): obj.Side = str(self.form.cutSide.currentData()) if obj.Direction != str(self.form.direction.currentData()): obj.Direction = str(self.form.direction.currentData()) - PathGui.updateInputField(obj, "OffsetExtra", self.form.extraOffset) + PathGuiUtil.updateInputField(obj, "OffsetExtra", self.form.extraOffset) if obj.UseComp != self.form.useCompensation.isChecked(): obj.UseComp = self.form.useCompensation.isChecked() @@ -169,4 +169,4 @@ Command = PathOpGui.SetupOperation( PathProfile.SetupProperties, ) -FreeCAD.Console.PrintLog("Loading PathProfileFacesGui... done\n") +FreeCAD.Console.PrintLog("Loading PathProfileGui ... done\n") diff --git a/src/Mod/Path/PathScripts/PathSelection.py b/src/Mod/Path/Path/Op/Gui/Selection.py similarity index 87% rename from src/Mod/Path/PathScripts/PathSelection.py rename to src/Mod/Path/Path/Op/Gui/Selection.py index 8e89cf95a2..9044e54a55 100644 --- a/src/Mod/Path/PathScripts/PathSelection.py +++ b/src/Mod/Path/Path/Op/Gui/Selection.py @@ -25,13 +25,12 @@ import FreeCAD import FreeCADGui -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.drillableLib as drillableLib +import Path +import Path.Base.Drillable as Drillable import math -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +# Path.Log.trackModule(Path.Log.thisModule()) class PathBaseGate(object): @@ -123,14 +122,14 @@ class CHAMFERGate(PathBaseGate): class DRILLGate(PathBaseGate): def allow(self, doc, obj, sub): - PathLog.debug("obj: {} sub: {}".format(obj, sub)) + Path.Log.debug("obj: {} sub: {}".format(obj, sub)) if not hasattr(obj, "Shape"): return False shape = obj.Shape subobj = shape.getElement(sub) if subobj.ShapeType not in ["Edge", "Face"]: return False - return drillableLib.isDrillable(shape, subobj, vector=None) + return Drillable.isDrillable(shape, subobj, vector=None) class FACEGate(PathBaseGate): @@ -233,11 +232,11 @@ class PROBEGate: class TURNGate(PathBaseGate): def allow(self, doc, obj, sub): - PathLog.debug("obj: {} sub: {}".format(obj, sub)) + Path.Log.debug("obj: {} sub: {}".format(obj, sub)) if hasattr(obj, "Shape") and sub: shape = obj.Shape subobj = shape.getElement(sub) - return drillableLib.isDrillable(shape, subobj, vector=None) + return Drillable.isDrillable(shape, subobj, vector=None) else: return False @@ -255,61 +254,61 @@ class ALLGate(PathBaseGate): def contourselect(): FreeCADGui.Selection.addSelectionGate(CONTOURGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Contour Select Mode\n") def eselect(): FreeCADGui.Selection.addSelectionGate(EGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Edge Select Mode\n") def drillselect(): FreeCADGui.Selection.addSelectionGate(DRILLGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Drilling Select Mode\n") def engraveselect(): FreeCADGui.Selection.addSelectionGate(ENGRAVEGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Engraving Select Mode\n") def fselect(): FreeCADGui.Selection.addSelectionGate(FACEGate()) # Was PROFILEGate() - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Profiling Select Mode\n") def chamferselect(): FreeCADGui.Selection.addSelectionGate(CHAMFERGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Deburr Select Mode\n") def profileselect(): FreeCADGui.Selection.addSelectionGate(PROFILEGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Profiling Select Mode\n") def pocketselect(): FreeCADGui.Selection.addSelectionGate(POCKETGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Pocketing Select Mode\n") def adaptiveselect(): FreeCADGui.Selection.addSelectionGate(ADAPTIVEGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Adaptive Select Mode\n") def slotselect(): FreeCADGui.Selection.addSelectionGate(ALLGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Slot Cutter Select Mode\n") @@ -318,30 +317,30 @@ def surfaceselect(): if MESHGate() or FACEGate(): gate = True FreeCADGui.Selection.addSelectionGate(gate) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Surfacing Select Mode\n") def vcarveselect(): FreeCADGui.Selection.addSelectionGate(VCARVEGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Vcarve Select Mode\n") def probeselect(): FreeCADGui.Selection.addSelectionGate(PROBEGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Probe Select Mode\n") def customselect(): - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Custom Select Mode\n") def turnselect(): FreeCADGui.Selection.addSelectionGate(TURNGate()) - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Turning Select Mode\n") @@ -377,5 +376,5 @@ def select(op): def clear(): FreeCADGui.Selection.removeSelectionGate() - if not PathPreferences.suppressSelectionModeWarning(): + if not Path.Preferences.suppressSelectionModeWarning(): FreeCAD.Console.PrintWarning("Free Select\n") diff --git a/src/Mod/Path/PathScripts/PathSimpleCopy.py b/src/Mod/Path/Path/Op/Gui/SimpleCopy.py similarity index 95% rename from src/Mod/Path/PathScripts/PathSimpleCopy.py rename to src/Mod/Path/Path/Op/Gui/SimpleCopy.py index 62e269408f..b8a21c3443 100644 --- a/src/Mod/Path/PathScripts/PathSimpleCopy.py +++ b/src/Mod/Path/Path/Op/Gui/SimpleCopy.py @@ -22,6 +22,7 @@ import FreeCAD import FreeCADGui +import Path import PathScripts from PySide.QtCore import QT_TRANSLATE_NOOP @@ -45,7 +46,7 @@ class CommandPathSimpleCopy: return False try: obj = FreeCADGui.Selection.getSelectionEx()[0].Object - return isinstance(obj.Proxy, PathScripts.PathOp.ObjectOp) + return isinstance(obj.Proxy, Path.Op.Base.ObjectOp) except Exception: return False @@ -71,9 +72,9 @@ class CommandPathSimpleCopy: ) FreeCADGui.addModule("PathScripts.PathUtils") - FreeCADGui.addModule("PathScripts.PathCustom") + FreeCADGui.addModule("Path.Op.Custom") FreeCADGui.doCommand( - 'obj = PathScripts.PathCustom.Create("' + 'obj = Path.Op.Custom.Create("' + selection[0].Name + '_SimpleCopy")' ) diff --git a/src/Mod/Path/PathScripts/PathSlotGui.py b/src/Mod/Path/Path/Op/Gui/Slot.py similarity index 97% rename from src/Mod/Path/PathScripts/PathSlotGui.py rename to src/Mod/Path/Path/Op/Gui/Slot.py index 3162844f8b..b1c56be72f 100644 --- a/src/Mod/Path/PathScripts/PathSlotGui.py +++ b/src/Mod/Path/Path/Op/Gui/Slot.py @@ -22,10 +22,10 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathSlot as PathSlot -import PathScripts.PathGui as PathGui -import PathScripts.PathOpGui as PathOpGui +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Slot as PathSlot +import PathGui from PySide import QtCore @@ -62,10 +62,10 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.setTitle("Slot - " + obj.Label) # retrieve property enumerations # Requirements due to Gui::QuantitySpinBox class use in UI panel - self.geo1Extension = PathGui.QuantitySpinBox( + self.geo1Extension = PathGuiUtil.QuantitySpinBox( self.form.geo1Extension, obj, "ExtendPathStart" ) - self.geo2Extension = PathGui.QuantitySpinBox( + self.geo2Extension = PathGuiUtil.QuantitySpinBox( self.form.geo2Extension, obj, "ExtendPathEnd" ) diff --git a/src/Mod/Path/PathScripts/PathStop.py b/src/Mod/Path/Path/Op/Gui/Stop.py similarity index 97% rename from src/Mod/Path/PathScripts/PathStop.py rename to src/Mod/Path/Path/Op/Gui/Stop.py index 196c9ce74a..b6dbba9a4f 100644 --- a/src/Mod/Path/PathScripts/PathStop.py +++ b/src/Mod/Path/Path/Op/Gui/Stop.py @@ -124,16 +124,16 @@ class CommandPathStop: FreeCAD.ActiveDocument.openTransaction( "Add Optional or Mandatory Stop to the program" ) - FreeCADGui.addModule("PathScripts.PathStop") + FreeCADGui.addModule("Path.Op.Gui.Stop") snippet = """ import Path import PathScripts from PathScripts import PathUtils prjexists = False obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Stop") -PathScripts.PathStop.Stop(obj) +Path.Op.Gui.Stop.Stop(obj) -PathScripts.PathStop._ViewProviderStop(obj.ViewObject) +Path.Op.Gui.Stop._ViewProviderStop(obj.ViewObject) PathUtils.addToJob(obj) """ FreeCADGui.doCommand(snippet) diff --git a/src/Mod/Path/PathScripts/PathSurfaceGui.py b/src/Mod/Path/Path/Op/Gui/Surface.py similarity index 95% rename from src/Mod/Path/PathScripts/PathSurfaceGui.py rename to src/Mod/Path/Path/Op/Gui/Surface.py index 6068b5292c..fd927a1204 100644 --- a/src/Mod/Path/PathScripts/PathSurfaceGui.py +++ b/src/Mod/Path/Path/Op/Gui/Surface.py @@ -23,11 +23,11 @@ from PySide import QtCore import FreeCAD import FreeCADGui -import PathScripts.PathLog as PathLog -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathGui as PathGui -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathSurface as PathSurface +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Surface as PathSurface +import PathGui __title__ = "Path Surface Operation UI" @@ -38,10 +38,10 @@ __doc__ = "Surface operation page controller and command implementation." translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class TaskPanelOpPage(PathOpGui.TaskPanelPage): @@ -66,7 +66,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): ("dropCutterDirSelect", "DropCutterDir"), ] enumTups = PathSurface.ObjectSurface.propertyEnumerations(dataType="raw") - PathGui.populateCombobox(form, enumTups, comboToPropertyMap) + PathGuiUtil.populateCombobox(form, enumTups, comboToPropertyMap) return form @@ -120,12 +120,12 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if obj.DropCutterDir != str(self.form.dropCutterDirSelect.currentData()): obj.DropCutterDir = str(self.form.dropCutterDirSelect.currentData()) - PathGui.updateInputField(obj, "DepthOffset", self.form.depthOffset) + PathGuiUtil.updateInputField(obj, "DepthOffset", self.form.depthOffset) if obj.StepOver != self.form.stepOver.value(): obj.StepOver = self.form.stepOver.value() - PathGui.updateInputField(obj, "SampleInterval", self.form.sampleInterval) + PathGuiUtil.updateInputField(obj, "SampleInterval", self.form.sampleInterval) if obj.UseStartPoint != self.form.useStartPoint.isChecked(): obj.UseStartPoint = self.form.useStartPoint.isChecked() diff --git a/src/Mod/Path/PathScripts/PathThreadMillingGui.py b/src/Mod/Path/Path/Op/Gui/ThreadMilling.py similarity index 92% rename from src/Mod/Path/PathScripts/PathThreadMillingGui.py rename to src/Mod/Path/Path/Op/Gui/ThreadMilling.py index 54ae450a15..464f78150e 100644 --- a/src/Mod/Path/PathScripts/PathThreadMillingGui.py +++ b/src/Mod/Path/Path/Op/Gui/ThreadMilling.py @@ -22,12 +22,12 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui -import PathScripts.PathThreadMilling as PathThreadMilling -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Gui.CircularHoleBase as PathCircularHoleBaseGui +import Path.Op.ThreadMilling as PathThreadMilling +import PathGui import csv from PySide.QtCore import QT_TRANSLATE_NOOP @@ -41,10 +41,10 @@ __url__ = "http://www.freecadweb.org" __doc__ = "UI and Command for Path Thread Milling Operation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -52,7 +52,7 @@ translate = FreeCAD.Qt.translate def fillThreads(form, dataFile, defaultSelect): form.threadName.blockSignals(True) select = form.threadName.currentText() - PathLog.debug("select = '{}'".format(select)) + Path.Log.debug("select = '{}'".format(select)) form.threadName.clear() with open( "{}Mod/Path/Data/Threads/{}".format(FreeCAD.getHomePath(), dataFile) @@ -72,13 +72,13 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): """Controller for the thread milling operation's page""" def initPage(self, obj): - self.majorDia = PathGui.QuantitySpinBox( + self.majorDia = PathGuiUtil.QuantitySpinBox( self.form.threadMajor, obj, "MajorDiameter" ) - self.minorDia = PathGui.QuantitySpinBox( + self.minorDia = PathGuiUtil.QuantitySpinBox( self.form.threadMinor, obj, "MinorDiameter" ) - self.pitch = PathGui.QuantitySpinBox(self.form.threadPitch, obj, "Pitch") + self.pitch = PathGuiUtil.QuantitySpinBox(self.form.threadPitch, obj, "Pitch") def getForm(self): """getForm() ... return UI""" @@ -97,7 +97,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): def getFields(self, obj): """getFields(obj) ... update obj's properties with values from the UI""" - PathLog.track() + Path.Log.track() self.majorDia.updateProperty() self.minorDia.updateProperty() @@ -115,7 +115,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): def setFields(self, obj): """setFields(obj) ... update UI with obj properties' values""" - PathLog.track() + Path.Log.track() self.selectInComboBox(obj.ThreadOrientation, self.form.threadOrientation) self.selectInComboBox(obj.ThreadType, self.form.threadType) diff --git a/src/Mod/Path/PathScripts/PathVcarveGui.py b/src/Mod/Path/Path/Op/Gui/Vcarve.py similarity index 91% rename from src/Mod/Path/PathScripts/PathVcarveGui.py rename to src/Mod/Path/Path/Op/Gui/Vcarve.py index c044763d71..d29194d9c4 100644 --- a/src/Mod/Path/PathScripts/PathVcarveGui.py +++ b/src/Mod/Path/Path/Op/Gui/Vcarve.py @@ -22,10 +22,10 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathVcarve as PathVcarve -import PathScripts.PathLog as PathLog -import PathScripts.PathOpGui as PathOpGui +import Path +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Vcarve as PathVcarve +import PathGui import PathScripts.PathUtils as PathUtils from PySide import QtCore, QtGui @@ -37,10 +37,10 @@ __doc__ = "Vcarve operation page controller and command implementation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -52,14 +52,14 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): return super(TaskPanelBaseGeometryPage, self) def addBaseGeometry(self, selection): - PathLog.track(selection) + Path.Log.track(selection) added = False shapes = self.obj.BaseShapes for sel in selection: job = PathUtils.findParentJob(self.obj) base = job.Proxy.resourceClone(job, sel.Object) if not base: - PathLog.notice( + Path.Log.notice( ( translate("Path", "%s is not a Base Model object of the job %s") + "\n" @@ -68,7 +68,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): ) continue if base in shapes: - PathLog.notice( + Path.Log.notice( "Base shape %s already in the list".format(sel.Object.Label) ) continue @@ -77,7 +77,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): # selectively add some elements of the drawing to the Base for sub in sel.SubElementNames: if "Vertex" in sub: - PathLog.info("Ignoring vertex") + Path.Log.info("Ignoring vertex") else: self.obj.Proxy.addBase(self.obj, base, sub) else: @@ -89,7 +89,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): if not added: # user wants us to engrave an edge of face of a base model - PathLog.info(" call default") + Path.Log.info(" call default") base = self.super().addBaseGeometry(selection) added = added or base @@ -106,7 +106,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): self.form.baseList.blockSignals(False) def updateBase(self): - PathLog.track() + Path.Log.track() shapes = [] for i in range(self.form.baseList.count()): item = self.form.baseList.item(i) @@ -114,7 +114,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): sub = item.data(self.super().DataObjectSub) if not sub: shapes.append(obj) - PathLog.debug( + Path.Log.debug( "Setting new base shapes: %s -> %s" % (self.obj.BaseShapes, shapes) ) self.obj.BaseShapes = shapes diff --git a/src/Mod/Path/PathScripts/PathWaterlineGui.py b/src/Mod/Path/Path/Op/Gui/Waterline.py similarity index 93% rename from src/Mod/Path/PathScripts/PathWaterlineGui.py rename to src/Mod/Path/Path/Op/Gui/Waterline.py index ed8548051b..41253d4d44 100644 --- a/src/Mod/Path/PathScripts/PathWaterlineGui.py +++ b/src/Mod/Path/Path/Op/Gui/Waterline.py @@ -25,10 +25,10 @@ from PySide import QtCore from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import FreeCADGui -import PathScripts.PathLog as PathLog -import PathScripts.PathGui as PathGui -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathWaterline as PathWaterline +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Op.Gui.Base as PathOpGui +import Path.Op.Waterline as PathWaterline __title__ = "Path Waterline Operation UI" __author__ = "sliptonic (Brad Collette), russ4262 (Russell Johnson)" @@ -38,10 +38,10 @@ __doc__ = "Waterline operation page controller and command implementation." translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class TaskPanelOpPage(PathOpGui.TaskPanelPage): @@ -61,7 +61,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): ("cutPattern", "CutPattern"), ] enumTups = PathWaterline.ObjectWaterline.propertyEnumerations(dataType="raw") - PathGui.populateCombobox(form, enumTups, comboToPropertyMap) + PathGuiUtil.populateCombobox(form, enumTups, comboToPropertyMap) return form def getFields(self, obj): @@ -81,14 +81,14 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if obj.CutPattern != str(self.form.cutPattern.currentData()): obj.CutPattern = str(self.form.cutPattern.currentData()) - PathGui.updateInputField( + PathGuiUtil.updateInputField( obj, "BoundaryAdjustment", self.form.boundaryAdjustment ) if obj.StepOver != self.form.stepOver.value(): obj.StepOver = self.form.stepOver.value() - PathGui.updateInputField(obj, "SampleInterval", self.form.sampleInterval) + PathGuiUtil.updateInputField(obj, "SampleInterval", self.form.sampleInterval) if obj.OptimizeLinearPaths != self.form.optimizeEnabled.isChecked(): obj.OptimizeLinearPaths = self.form.optimizeEnabled.isChecked() diff --git a/src/Mod/Path/Path/Op/Gui/__init__.py b/src/Mod/Path/Path/Op/Gui/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/PathHelix.py b/src/Mod/Path/Path/Op/Helix.py similarity index 94% rename from src/Mod/Path/PathScripts/PathHelix.py rename to src/Mod/Path/Path/Op/Helix.py index 0b2eaf8a73..efc94c4f2c 100644 --- a/src/Mod/Path/PathScripts/PathHelix.py +++ b/src/Mod/Path/Path/Op/Helix.py @@ -20,17 +20,16 @@ # * * # *************************************************************************** -from Generators import helix_generator +import Path.Base.Generator.helix as helix from PathScripts.PathUtils import fmt from PathScripts.PathUtils import sort_locations from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Part import Path -import PathScripts.PathCircularHoleBase as PathCircularHoleBase -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathFeedRate +import Path.Base.FeedRate as PathFeedRate +import Path.Op.Base as PathOp +import Path.Op.CircularHoleBase as PathCircularHoleBase __title__ = "Path Helix Drill Operation" @@ -44,10 +43,10 @@ __lastModified__ = "2019-07-12 09:50 CST" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -84,11 +83,11 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -170,7 +169,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): def circularHoleExecute(self, obj, holes): """circularHoleExecute(obj, holes) ... generate helix commands for each hole in holes""" - PathLog.track() + Path.Log.track() self.commandlist.append(Path.Command("(helix cut operation)")) self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) @@ -219,7 +218,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): ) ) - results = helix_generator.generate(**args) + results = helix.generate(**args) for command in results: self.commandlist.append(command) diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/Path/Op/MillFace.py similarity index 94% rename from src/Mod/Path/PathScripts/PathMillFace.py rename to src/Mod/Path/Path/Op/MillFace.py index 59e42aace2..f633492ae5 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/Path/Op/MillFace.py @@ -23,8 +23,8 @@ from __future__ import print_function import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathPocketBase as PathPocketBase +import Path +import Path.Op.PocketBase as PathPocketBase import PathScripts.PathUtils as PathUtils from PySide.QtCore import QT_TRANSLATE_NOOP import numpy @@ -42,10 +42,10 @@ __contributors__ = "russ4262 (Russell Johnson)" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -79,16 +79,16 @@ class ObjectFace(PathPocketBase.ObjectPocket): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data def initPocketOp(self, obj): - PathLog.track() + Path.Log.track() """initPocketOp(obj) ... create facing specific properties""" obj.addProperty( "App::PropertyEnumeration", @@ -122,7 +122,7 @@ class ObjectFace(PathPocketBase.ObjectPocket): def areaOpOnChanged(self, obj, prop): """areaOpOnChanged(obj, prop) ... facing specific depths calculation.""" - PathLog.track(prop) + Path.Log.track(prop) if prop == "StepOver" and obj.StepOver == 0: obj.StepOver = 1 @@ -133,7 +133,7 @@ class ObjectFace(PathPocketBase.ObjectPocket): obj.OpStartDepth = job.Stock.Shape.BoundBox.ZMax if len(obj.Base) >= 1: - PathLog.debug("processing") + Path.Log.debug("processing") sublist = [] for i in obj.Base: o = i[0] @@ -154,10 +154,10 @@ class ObjectFace(PathPocketBase.ObjectPocket): self.removalshapes = [] holeShape = None - PathLog.debug("depthparams: {}".format([i for i in self.depthparams])) + Path.Log.debug("depthparams: {}".format([i for i in self.depthparams])) if obj.Base: - PathLog.debug("obj.Base: {}".format(obj.Base)) + Path.Log.debug("obj.Base: {}".format(obj.Base)) faces = [] holes = [] holeEnvs = [] @@ -187,7 +187,7 @@ class ObjectFace(PathPocketBase.ObjectPocket): else: holes.append((b[0].Shape, wire)) else: - PathLog.warning( + Path.Log.warning( 'The base subobject, "{0}," is not a face. Ignoring "{0}."'.format( sub ) @@ -202,16 +202,16 @@ class ObjectFace(PathPocketBase.ObjectPocket): holeEnvs.append(env) holeShape = Part.makeCompound(holeEnvs) - PathLog.debug("Working on a collection of faces {}".format(faces)) + Path.Log.debug("Working on a collection of faces {}".format(faces)) planeshape = Part.makeCompound(faces) # If no base object, do planing of top surface of entire model else: planeshape = Part.makeCompound([base.Shape for base in self.model]) - PathLog.debug("Working on a shape {}".format(obj.Label)) + Path.Log.debug("Working on a shape {}".format(obj.Label)) # Find the correct shape depending on Boundary shape. - PathLog.debug("Boundary Shape: {}".format(obj.BoundaryShape)) + Path.Log.debug("Boundary Shape: {}".format(obj.BoundaryShape)) bb = planeshape.BoundBox # Apply offset for clearing edges @@ -307,14 +307,14 @@ class ObjectFace(PathPocketBase.ObjectPocket): env = ofstShapeEnv if holeShape: - PathLog.debug("Processing holes and face ...") + Path.Log.debug("Processing holes and face ...") holeEnv = PathUtils.getEnvelope( partshape=holeShape, depthparams=self.depthparams ) newEnv = env.cut(holeEnv) tup = newEnv, False, "pathMillFace" else: - PathLog.debug("Processing solid face ...") + Path.Log.debug("Processing solid face ...") tup = env, False, "pathMillFace" self.removalshapes.append(tup) diff --git a/src/Mod/Path/PathScripts/PathPocket.py b/src/Mod/Path/Path/Op/Pocket.py similarity index 95% rename from src/Mod/Path/PathScripts/PathPocket.py rename to src/Mod/Path/Path/Op/Pocket.py index 2db07d5b36..2453f613d0 100644 --- a/src/Mod/Path/PathScripts/PathPocket.py +++ b/src/Mod/Path/Path/Op/Pocket.py @@ -23,16 +23,14 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Part -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.PathPocketBase as PathPocketBase +import Path +import Path.Op.Base as PathOp +import Path.Op.PocketBase as PathPocketBase import PathScripts.PathUtils as PathUtils # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader -PathGeom = LazyLoader("PathScripts.PathGeom", globals(), "PathScripts.PathGeom") - __title__ = "Path 3D Pocket Operation" __author__ = "Yorik van Havre " __url__ = "https://www.freecadweb.org" @@ -40,10 +38,10 @@ __doc__ = "Class and implementation of the 3D Pocket operation." __created__ = "2014" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -127,11 +125,11 @@ class ObjectPocket(PathPocketBase.ObjectPocket): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -154,15 +152,15 @@ class ObjectPocket(PathPocketBase.ObjectPocket): def areaOpShapes(self, obj): """areaOpShapes(obj) ... return shapes representing the solids to be removed.""" - PathLog.track() + Path.Log.track() subObjTups = [] removalshapes = [] if obj.Base: - PathLog.debug("base items exist. Processing... ") + Path.Log.debug("base items exist. Processing... ") for base in obj.Base: - PathLog.debug("obj.Base item: {}".format(base)) + Path.Log.debug("obj.Base item: {}".format(base)) # Check if all subs are faces allSubsFaceType = True @@ -185,7 +183,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): ): (fzmin, fzmax) = self.getMinMaxOfFaces(Faces) if obj.FinalDepth.Value < fzmin: - PathLog.warning( + Path.Log.warning( translate( "PathPocket", "Final depth set below ZMin of face(s) selected.", @@ -234,7 +232,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): removalshapes.append((obj.removalshape, False, "3DPocket")) else: # process the job base object as a whole - PathLog.debug("processing the whole job base object") + Path.Log.debug("processing the whole job base object") for base in self.model: if obj.ProcessStockArea is True: job = PathUtils.findParentJob(obj) @@ -254,7 +252,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): removalSolids = [ s for s in rawRemovalShape.Solids - if PathGeom.isRoughly( + if Path.Geom.isRoughly( s.BoundBox.ZMax, rawRemovalShape.BoundBox.ZMax ) ] @@ -326,8 +324,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket): try: highFaceShape = Part.Face(Part.Wire(Part.__sortEdges__(allEdges))) except Exception as ee: - PathLog.warning(ee) - PathLog.error( + Path.Log.warning(ee) + Path.Log.error( translate( "Path", "A planar adaptive start is unavailable. The non-planar will be attempted.", @@ -343,8 +341,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket): Part.__sortEdges__(allEdges) ) # NON-planar face method except Exception as eee: - PathLog.warning(eee) - PathLog.error( + Path.Log.warning(eee) + Path.Log.error( translate( "Path", "The non-planar adaptive start is also unavailable." ) @@ -368,13 +366,13 @@ class ObjectPocket(PathPocketBase.ObjectPocket): highFace.Shape.BoundBox.ZMax > mx or highFace.Shape.BoundBox.ZMin < mn ): - PathLog.warning( + Path.Log.warning( "ZMaxDiff: {}; ZMinDiff: {}".format( highFace.Shape.BoundBox.ZMax - mx, highFace.Shape.BoundBox.ZMin - mn, ) ) - PathLog.error( + Path.Log.error( translate( "Path", "The non-planar adaptive start is also unavailable." ) @@ -397,8 +395,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket): lowFaceShape = Part.Face(Part.Wire(Part.__sortEdges__(allEdges))) # lowFaceShape = Part.makeFilledFace(Part.__sortEdges__(allEdges)) # NON-planar face method except Exception as ee: - PathLog.error(ee) - PathLog.error("An adaptive finish is unavailable.") + Path.Log.error(ee) + Path.Log.error("An adaptive finish is unavailable.") isLowFacePlanar = False else: FreeCAD.ActiveDocument.addObject("Part::Feature", "bottomEdgeFace") @@ -633,7 +631,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): for ei2 in range(0, len(face2.Edges)): edg2 = face2.Edges[ei2] if edg1.isSame(edg2) is True: - PathLog.debug( + Path.Log.debug( "{}.Edges[{}] connects at {}.Edges[{}]".format( sub1, ei1, sub2, ei2 ) @@ -704,7 +702,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): Compare vertexes of two edges to identify a common vertex. Returns the vertex index of edge1 to which edge2 is connected""" if show is True: - PathLog.info("New findCommonVertex()... ") + Path.Log.info("New findCommonVertex()... ") oIdx = 0 listOne = edge1.Vertexes @@ -713,15 +711,15 @@ class ObjectPocket(PathPocketBase.ObjectPocket): # Find common vertexes for o in listOne: if show is True: - PathLog.info(" one ({}, {}, {})".format(o.X, o.Y, o.Z)) + Path.Log.info(" one ({}, {}, {})".format(o.X, o.Y, o.Z)) for t in listTwo: if show is True: - PathLog.error("two ({}, {}, {})".format(t.X, t.Y, t.Z)) + Path.Log.error("two ({}, {}, {})".format(t.X, t.Y, t.Z)) if o.X == t.X: if o.Y == t.Y: if o.Z == t.Z: if show is True: - PathLog.info("found") + Path.Log.info("found") return oIdx oIdx += 1 return -1 @@ -773,7 +771,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): while len(holds) > 0: if loops > 500: - PathLog.error("BREAK --- LOOPS LIMIT of 500 ---") + Path.Log.error("BREAK --- LOOPS LIMIT of 500 ---") break save = False @@ -893,7 +891,7 @@ def _extrudeBaseDown(base): Extrudes and fuses all non-vertical faces downward to a level 1.0 mm below base ZMin.""" allExtrusions = list() zMin = base.Shape.BoundBox.ZMin - bbFace = PathGeom.makeBoundBoxFace(base.Shape.BoundBox, offset=5.0) + bbFace = Path.Geom.makeBoundBoxFace(base.Shape.BoundBox, offset=5.0) bbFace.translate( FreeCAD.Vector(0.0, 0.0, float(int(base.Shape.BoundBox.ZMin - 5.0))) ) @@ -902,7 +900,7 @@ def _extrudeBaseDown(base): # Make projections of each non-vertical face and extrude it for f in base.Shape.Faces: fbb = f.BoundBox - if not PathGeom.isRoughly(f.normalAt(0, 0).z, 0.0): + if not Path.Geom.isRoughly(f.normalAt(0, 0).z, 0.0): pp = bbFace.makeParallelProjection(f.Wires[0], direction) face = Part.Face(Part.Wire(pp.Edges)) face.translate(FreeCAD.Vector(0.0, 0.0, fbb.ZMin)) diff --git a/src/Mod/Path/PathScripts/PathPocketBase.py b/src/Mod/Path/Path/Op/PocketBase.py similarity index 95% rename from src/Mod/Path/PathScripts/PathPocketBase.py rename to src/Mod/Path/Path/Op/PocketBase.py index b8f78810fb..e032b0a610 100644 --- a/src/Mod/Path/PathScripts/PathPocketBase.py +++ b/src/Mod/Path/Path/Op/PocketBase.py @@ -21,10 +21,11 @@ # *************************************************************************** import FreeCAD +import Path +import Path.Op.Area as PathAreaOp +import Path.Op.Base as PathOp + from PySide.QtCore import QT_TRANSLATE_NOOP -import PathScripts.PathAreaOp as PathAreaOp -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp __title__ = "Base Path Pocket Operation" @@ -33,10 +34,10 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Base class and implementation for Path pocket operations." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -79,11 +80,11 @@ class ObjectPocket(PathAreaOp.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -114,7 +115,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): def initAreaOp(self, obj): """initAreaOp(obj) ... create pocket specific properties. Do not overwrite, implement initPocketOp(obj) instead.""" - PathLog.track() + Path.Log.track() # Pocket Properties obj.addProperty( @@ -191,7 +192,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): self.initPocketOp(obj) def areaOpRetractTool(self, obj): - PathLog.debug("retracting tool: %d" % (not obj.KeepToolDown)) + Path.Log.debug("retracting tool: %d" % (not obj.KeepToolDown)) return not obj.KeepToolDown def areaOpUseProjection(self, obj): @@ -200,7 +201,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): def areaOpAreaParams(self, obj, isHole): """areaOpAreaParams(obj, isHole) ... return dictionary with pocket's area parameters""" - PathLog.track() + Path.Log.track() params = {} params["Fill"] = 0 params["Coplanar"] = 0 @@ -245,7 +246,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): ), ) obj.PocketLastStepOver = 0 - PathLog.track() + Path.Log.track() def areaOpPathParams(self, obj, isHole): """areaOpAreaParams(obj, isHole) ... return dictionary with pocket's path parameters""" diff --git a/src/Mod/Path/PathScripts/PathPocketShape.py b/src/Mod/Path/Path/Op/PocketShape.py similarity index 83% rename from src/Mod/Path/PathScripts/PathPocketShape.py rename to src/Mod/Path/Path/Op/PocketShape.py index ba5d99c7a3..1a1817f1e2 100644 --- a/src/Mod/Path/PathScripts/PathPocketShape.py +++ b/src/Mod/Path/Path/Op/PocketShape.py @@ -22,10 +22,9 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.PathPocketBase as PathPocketBase +import Path +import Path.Op.Base as PathOp +import Path.Op.PocketBase as PathPocketBase # lazily loaded modules @@ -36,7 +35,7 @@ TechDraw = LazyLoader("TechDraw", globals(), "TechDraw") math = LazyLoader("math", globals(), "math") PathUtils = LazyLoader("PathScripts.PathUtils", globals(), "PathScripts.PathUtils") FeatureExtensions = LazyLoader( - "PathScripts.PathFeatureExtensions", globals(), "PathScripts.PathFeatureExtensions" + "Path.Op.FeatureExtension", globals(), "Path.Op.FeatureExtension" ) @@ -47,10 +46,10 @@ __doc__ = "Class and implementation of shape based Pocket operation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectPocket(PathPocketBase.ObjectPocket): @@ -89,10 +88,10 @@ class ObjectPocket(PathPocketBase.ObjectPocket): def areaOpShapes(self, obj): """areaOpShapes(obj) ... return shapes representing the solids to be removed.""" - PathLog.track() + Path.Log.track() self.removalshapes = [] - # self.isDebug = True if PathLog.getLevel(PathLog.thisModule()) == 4 else False + # self.isDebug = True if Path.Log.getLevel(Path.Log.thisModule()) == 4 else False self.removalshapes = [] avoidFeatures = list() @@ -103,14 +102,14 @@ class ObjectPocket(PathPocketBase.ObjectPocket): avoidFeatures.append(e.feature) if obj.Base: - PathLog.debug("base items exist. Processing...") + Path.Log.debug("base items exist. Processing...") self.horiz = [] self.vert = [] for (base, subList) in obj.Base: for sub in subList: if "Face" in sub: if sub not in avoidFeatures and not self.clasifySub(base, sub): - PathLog.error( + Path.Log.error( "Pocket does not support shape {}.{}".format( base.Label, sub ) @@ -123,17 +122,17 @@ class ObjectPocket(PathPocketBase.ObjectPocket): # Check if selected vertical faces form a loop if len(self.vert) > 0: - self.vertical = PathGeom.combineConnectedShapes(self.vert) + self.vertical = Path.Geom.combineConnectedShapes(self.vert) self.vWires = [ TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical ] for wire in self.vWires: - w = PathGeom.removeDuplicateEdges(wire) + w = Path.Geom.removeDuplicateEdges(wire) face = Part.Face(w) # face.tessellate(0.1) - if PathGeom.isRoughly(face.Area, 0): - PathLog.error("Vertical faces do not form a loop - ignoring") + if Path.Geom.isRoughly(face.Area, 0): + Path.Log.error("Vertical faces do not form a loop - ignoring") else: self.horiz.append(face) @@ -149,7 +148,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): self.exts.append(f) # check all faces and see if they are touching/overlapping and combine and simplify - self.horizontal = PathGeom.combineHorizontalFaces(self.horiz) + self.horizontal = Path.Geom.combineHorizontalFaces(self.horiz) # Move all faces to final depth less buffer before extrusion # Small negative buffer is applied to compensate for internal significant digits/rounding issue @@ -174,7 +173,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): ] else: # process the job base object as a whole - PathLog.debug("processing the whole job base object") + Path.Log.debug("processing the whole job base object") self.outlines = [ Part.Face( TechDraw.findShapeOutline(base.Shape, 1, FreeCAD.Vector(0, 0, 1)) @@ -202,11 +201,11 @@ class ObjectPocket(PathPocketBase.ObjectPocket): # Support methods def isVerticalExtrusionFace(self, face): fBB = face.BoundBox - if PathGeom.isRoughly(fBB.ZLength, 0.0): + if Path.Geom.isRoughly(fBB.ZLength, 0.0): return False extr = face.extrude(FreeCAD.Vector(0.0, 0.0, fBB.ZLength)) if hasattr(extr, "Volume"): - if PathGeom.isRoughly(extr.Volume, 0.0): + if Path.Geom.isRoughly(extr.Volume, 0.0): return True return False @@ -218,28 +217,28 @@ class ObjectPocket(PathPocketBase.ObjectPocket): face = bs.Shape.getElement(sub) if type(face.Surface) == Part.Plane: - PathLog.debug("type() == Part.Plane") - if PathGeom.isVertical(face.Surface.Axis): - PathLog.debug(" -isVertical()") + Path.Log.debug("type() == Part.Plane") + if Path.Geom.isVertical(face.Surface.Axis): + Path.Log.debug(" -isVertical()") # it's a flat horizontal face self.horiz.append(face) return True - elif PathGeom.isHorizontal(face.Surface.Axis): - PathLog.debug(" -isHorizontal()") + elif Path.Geom.isHorizontal(face.Surface.Axis): + Path.Log.debug(" -isHorizontal()") self.vert.append(face) return True else: return False - elif type(face.Surface) == Part.Cylinder and PathGeom.isVertical( + elif type(face.Surface) == Part.Cylinder and Path.Geom.isVertical( face.Surface.Axis ): - PathLog.debug("type() == Part.Cylinder") + Path.Log.debug("type() == Part.Cylinder") # vertical cylinder wall if any(e.isClosed() for e in face.Edges): - PathLog.debug(" -e.isClosed()") + Path.Log.debug(" -e.isClosed()") # complete cylinder circle = Part.makeCircle(face.Surface.Radius, face.Surface.Center) disk = Part.Face(Part.Wire(circle)) @@ -250,23 +249,23 @@ class ObjectPocket(PathPocketBase.ObjectPocket): return True else: - PathLog.debug(" -none isClosed()") + Path.Log.debug(" -none isClosed()") # partial cylinder wall self.vert.append(face) return True elif type(face.Surface) == Part.SurfaceOfExtrusion: # extrusion wall - PathLog.debug("type() == Part.SurfaceOfExtrusion") + Path.Log.debug("type() == Part.SurfaceOfExtrusion") # Save face to self.horiz for processing or display error if self.isVerticalExtrusionFace(face): self.vert.append(face) return True else: - PathLog.error("Failed to identify vertical face from {}".format(sub)) + Path.Log.error("Failed to identify vertical face from {}".format(sub)) else: - PathLog.debug(" -type(face.Surface): {}".format(type(face.Surface))) + Path.Log.debug(" -type(face.Surface): {}".format(type(face.Surface))) return False diff --git a/src/Mod/Path/PathScripts/PathProbe.py b/src/Mod/Path/Path/Op/Probe.py similarity index 95% rename from src/Mod/Path/PathScripts/PathProbe.py rename to src/Mod/Path/Path/Op/Probe.py index dbb2b2c0e9..81ed2fdbb5 100644 --- a/src/Mod/Path/PathScripts/PathProbe.py +++ b/src/Mod/Path/Path/Op/Probe.py @@ -24,8 +24,7 @@ from __future__ import print_function import FreeCAD import Path -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp +import Path.Op.Base as PathOp import PathScripts.PathUtils as PathUtils from PySide.QtCore import QT_TRANSLATE_NOOP @@ -36,10 +35,10 @@ __url__ = "http://www.freecadweb.org" __doc__ = "Path Probing operation." if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectProbing(PathOp.ObjectOp): @@ -96,7 +95,7 @@ class ObjectProbing(PathOp.ObjectOp): def opExecute(self, obj): """opExecute(obj) ... generate probe locations.""" - PathLog.track() + Path.Log.track() self.commandlist.append(Path.Command("(Begin Probing)")) stock = PathUtils.findParentJob(obj).Stock diff --git a/src/Mod/Path/PathScripts/PathProfile.py b/src/Mod/Path/Path/Op/Profile.py similarity index 92% rename from src/Mod/Path/PathScripts/PathProfile.py rename to src/Mod/Path/Path/Op/Profile.py index 7066966d79..92e17606a3 100644 --- a/src/Mod/Path/PathScripts/PathProfile.py +++ b/src/Mod/Path/Path/Op/Profile.py @@ -24,11 +24,10 @@ import FreeCAD import Path -import PathScripts.PathAreaOp as PathAreaOp -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp +import Path.Base.Drillable as Drillable +import Path.Op.Area as PathAreaOp +import Path.Op.Base as PathOp import PathScripts.PathUtils as PathUtils -import PathScripts.drillableLib as drillableLib import math import numpy from PySide.QtCore import QT_TRANSLATE_NOOP @@ -50,10 +49,10 @@ __doc__ = ( __contributors__ = "Schildkroet" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectProfile(PathAreaOp.ObjectOp): @@ -218,12 +217,12 @@ class ObjectProfile(PathAreaOp.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): # data[k] = [tup[idx] for tup in v] data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -375,7 +374,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): shapes = [] remainingObjBaseFeatures = [] - self.isDebug = True if PathLog.getLevel(PathLog.thisModule()) == 4 else False + self.isDebug = True if Path.Log.getLevel(Path.Log.thisModule()) == 4 else False self.inaccessibleMsg = translate( "PathProfile", "The selected edge(s) are inaccessible. If multiple, re-ordering selection might work.", @@ -412,12 +411,12 @@ class ObjectProfile(PathAreaOp.ObjectOp): obj.Base and len(obj.Base) > 0 ): # The user has selected subobjects from the base. Process each. shapes.extend(self._processEdges(obj, remainingObjBaseFeatures)) - PathLog.track("returned {} shapes".format(len(shapes))) + Path.Log.track("returned {} shapes".format(len(shapes))) - PathLog.track(remainingObjBaseFeatures) + Path.Log.track(remainingObjBaseFeatures) if obj.Base and len(obj.Base) > 0 and not remainingObjBaseFeatures: # Edges were already processed, or whole model targeted. - PathLog.track("remainingObjBaseFeatures is False") + Path.Log.track("remainingObjBaseFeatures is False") elif ( remainingObjBaseFeatures and len(remainingObjBaseFeatures) > 0 ): # Process remaining features after edges processed above. @@ -434,7 +433,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): if numpy.isclose( abs(shape.normalAt(0, 0).z), 1 ): # horizontal face - PathLog.debug(abs(shape.normalAt(0, 0).z)) + Path.Log.debug(abs(shape.normalAt(0, 0).z)) for wire in shape.Wires: if wire.hashCode() == shape.OuterWire.hashCode(): continue @@ -443,16 +442,16 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Add face depth to list faceDepths.append(shape.BoundBox.ZMin) else: - PathLog.track() + Path.Log.track() ignoreSub = base.Name + "." + sub msg = "Found a selected object which is not a face. Ignoring:" - PathLog.warning(msg + " {}".format(ignoreSub)) + Path.Log.warning(msg + " {}".format(ignoreSub)) for baseShape, wire in holes: cont = False f = Part.makeFace(wire, "Part::FaceMakerSimple") - drillable = drillableLib.isDrillable(baseShape, f, vector=None) - PathLog.debug(drillable) + drillable = Drillable.isDrillable(baseShape, f, vector=None) + Path.Log.debug(drillable) if obj.processCircles: if drillable: @@ -486,7 +485,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): msg = translate( "PathProfile", "Unable to create path for face(s)." ) - PathLog.error(msg + "\n{}".format(ee)) + Path.Log.error(msg + "\n{}".format(ee)) cont = False if cont: @@ -508,17 +507,17 @@ class ObjectProfile(PathAreaOp.ObjectOp): else: # Try to build targets from the job models # No base geometry selected, so treating operation like a exterior contour operation - PathLog.track() + Path.Log.track() self.opUpdateDepths(obj) if 1 == len(self.model) and hasattr(self.model[0], "Proxy"): - PathLog.debug("Single model processed.") + Path.Log.debug("Single model processed.") shapes.extend(self._processEachModel(obj)) else: shapes.extend(self._processEachModel(obj)) self.removalshapes = shapes - PathLog.debug("%d shapes" % len(shapes)) + Path.Log.debug("%d shapes" % len(shapes)) # Delete the temporary objects if self.isDebug: @@ -547,7 +546,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Edges pre-processing def _processEdges(self, obj, remainingObjBaseFeatures): - PathLog.track("remainingObjBaseFeatures: {}".format(remainingObjBaseFeatures)) + Path.Log.track("remainingObjBaseFeatures: {}".format(remainingObjBaseFeatures)) shapes = [] basewires = [] ezMin = None @@ -572,7 +571,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): if len(keepFaces) > 0: # save faces for returning and processing remainingObjBaseFeatures.append((base, keepFaces)) - PathLog.track(basewires) + Path.Log.track(basewires) for base, wires in basewires: for wire in wires: if wire.isClosed(): @@ -592,13 +591,13 @@ class ObjectProfile(PathAreaOp.ObjectOp): tup = shapeEnv, False, "pathProfile" shapes.append(tup) else: - PathLog.error(self.inaccessibleMsg) + Path.Log.error(self.inaccessibleMsg) else: # Attempt open-edges profile if self.JOB.GeometryTolerance.Value == 0.0: msg = self.JOB.Label + ".GeometryTolerance = 0.0. " msg += "Please set to an acceptable value greater than zero." - PathLog.error(msg) + Path.Log.error(msg) else: flattened = self._flattenWire(obj, wire, obj.FinalDepth.Value) zDiff = math.fabs(wire.BoundBox.ZMin - obj.FinalDepth.Value) @@ -624,7 +623,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): for cW in cutWireObjs: openEdges.append(cW) else: - PathLog.error(self.inaccessibleMsg) + Path.Log.error(self.inaccessibleMsg) if openEdges: tup = openEdges, False, "OpenEdge" @@ -635,9 +634,9 @@ class ObjectProfile(PathAreaOp.ObjectOp): "PathProfile", "Check edge selection and Final Depth requirements for profiling open edge(s).", ) - PathLog.error(msg) + Path.Log.error(msg) else: - PathLog.error(self.inaccessibleMsg) + Path.Log.error(self.inaccessibleMsg) # Eif # Eif # Efor @@ -647,11 +646,11 @@ class ObjectProfile(PathAreaOp.ObjectOp): def _flattenWire(self, obj, wire, trgtDep): """_flattenWire(obj, wire)... Return a flattened version of the wire""" - PathLog.debug("_flattenWire()") + Path.Log.debug("_flattenWire()") wBB = wire.BoundBox if wBB.ZLength > 0.0: - PathLog.debug("Wire is not horizontally co-planar. Flattening it.") + Path.Log.debug("Wire is not horizontally co-planar. Flattening it.") # Extrude non-horizontal wire extFwdLen = (wBB.ZLength + 2.0) * 2.0 @@ -672,7 +671,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Open-edges methods def _getCutAreaCrossSection(self, obj, base, origWire, flatWire): - PathLog.debug("_getCutAreaCrossSection()") + Path.Log.debug("_getCutAreaCrossSection()") # FCAD = FreeCAD.ActiveDocument tolerance = self.JOB.GeometryTolerance.Value toolDiam = ( @@ -758,14 +757,14 @@ class ObjectProfile(PathAreaOp.ObjectOp): ): botFc.append(f) if len(topFc) == 0: - PathLog.error("Failed to identify top faces of cut area.") + Path.Log.error("Failed to identify top faces of cut area.") return False topComp = Part.makeCompound([cutArea.Faces[f] for f in topFc]) topComp.translate( FreeCAD.Vector(0, 0, fdv - topComp.BoundBox.ZMin) ) # Translate face to final depth if len(botFc) > 1: - # PathLog.debug('len(botFc) > 1') + # Path.Log.debug('len(botFc) > 1') bndboxFace = Part.Face(extBndbox.Wires[0]) tmpFace = Part.Face(extBndbox.Wires[0]) for f in botFc: @@ -786,12 +785,12 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Determine with which set of intersection tags the model intersects (cmnIntArea, cmnExtArea) = self._checkTagIntersection(iTAG, eTAG, "QRY", comFC) if cmnExtArea > cmnIntArea: - PathLog.debug("Cutting on Ext side.") + Path.Log.debug("Cutting on Ext side.") self.cutSide = "E" self.cutSideTags = eTAG tagCOM = begExt.CenterOfMass else: - PathLog.debug("Cutting on Int side.") + Path.Log.debug("Cutting on Int side.") self.cutSide = "I" self.cutSideTags = iTAG tagCOM = begInt.CenterOfMass @@ -836,12 +835,12 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Efor if wi is None: - PathLog.error( + Path.Log.error( "The cut area cross-section wire does not coincide with selected edge. Wires[] index is None." ) return False else: - PathLog.debug("Cross-section Wires[] index is {}.".format(wi)) + Path.Log.debug("Cross-section Wires[] index is {}.".format(wi)) nWire = Part.Wire(Part.__sortEdges__(workShp.Wires[wi].Edges)) fcShp = Part.Face(nWire) @@ -850,22 +849,22 @@ class ObjectProfile(PathAreaOp.ObjectOp): # verify that wire chosen is not inside the physical model if wi > 0: # and isInterior is False: - PathLog.debug("Multiple wires in cut area. First choice is not 0. Testing.") + Path.Log.debug("Multiple wires in cut area. First choice is not 0. Testing.") testArea = fcShp.cut(base.Shape) isReady = self._checkTagIntersection(iTAG, eTAG, self.cutSide, testArea) - PathLog.debug("isReady {}.".format(isReady)) + Path.Log.debug("isReady {}.".format(isReady)) if isReady is False: - PathLog.debug("Using wire index {}.".format(wi - 1)) + Path.Log.debug("Using wire index {}.".format(wi - 1)) pWire = Part.Wire(Part.__sortEdges__(workShp.Wires[wi - 1].Edges)) pfcShp = Part.Face(pWire) pfcShp.translate(FreeCAD.Vector(0, 0, fdv - workShp.BoundBox.ZMin)) workShp = pfcShp.cut(fcShp) if testArea.Area < minArea: - PathLog.debug("offset area is less than minArea of {}.".format(minArea)) - PathLog.debug("Using wire index {}.".format(wi - 1)) + Path.Log.debug("offset area is less than minArea of {}.".format(minArea)) + Path.Log.debug("Using wire index {}.".format(wi - 1)) pWire = Part.Wire(Part.__sortEdges__(workShp.Wires[wi - 1].Edges)) pfcShp = Part.Face(pWire) pfcShp.translate(FreeCAD.Vector(0, 0, fdv - workShp.BoundBox.ZMin)) @@ -879,7 +878,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return cutShp def _checkTagIntersection(self, iTAG, eTAG, cutSide, tstObj): - PathLog.debug("_checkTagIntersection()") + Path.Log.debug("_checkTagIntersection()") # Identify intersection of Common area and Interior Tags intCmn = tstObj.common(iTAG) @@ -893,17 +892,17 @@ class ObjectProfile(PathAreaOp.ObjectOp): return (cmnIntArea, cmnExtArea) if cmnExtArea > cmnIntArea: - PathLog.debug("Cutting on Ext side.") + Path.Log.debug("Cutting on Ext side.") if cutSide == "E": return True else: - PathLog.debug("Cutting on Int side.") + Path.Log.debug("Cutting on Int side.") if cutSide == "I": return True return False def _extractPathWire(self, obj, base, flatWire, cutShp): - PathLog.debug("_extractPathWire()") + Path.Log.debug("_extractPathWire()") subLoops = [] rtnWIRES = [] @@ -929,10 +928,10 @@ class ObjectProfile(PathAreaOp.ObjectOp): if osArea: # Make LGTM parser happy pass else: - PathLog.error("No area to offset shape returned.") + Path.Log.error("No area to offset shape returned.") return [] except Exception as ee: - PathLog.error("No area to offset shape returned.\n{}".format(ee)) + Path.Log.error("No area to offset shape returned.\n{}".format(ee)) return [] self._addDebugObject("OffsetShape", ofstShp) @@ -967,7 +966,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): self._addDebugObject("Near1", near1Shp) if w0 != w1: - PathLog.warning( + Path.Log.warning( "Offset wire endpoint indexes are not equal - w0, w1: {}, {}".format( w0, w1 ) @@ -976,12 +975,12 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Debugging """ if self.isDebug: - PathLog.debug('min0i is {}.'.format(min0i)) - PathLog.debug('min1i is {}.'.format(min1i)) - PathLog.debug('NEAR0[{}] is {}.'.format(w0, NEAR0[w0])) - PathLog.debug('NEAR1[{}] is {}.'.format(w1, NEAR1[w1])) - PathLog.debug('NEAR0 is {}.'.format(NEAR0)) - PathLog.debug('NEAR1 is {}.'.format(NEAR1)) + Path.Log.debug('min0i is {}.'.format(min0i)) + Path.Log.debug('min1i is {}.'.format(min1i)) + Path.Log.debug('NEAR0[{}] is {}.'.format(w0, NEAR0[w0])) + Path.Log.debug('NEAR1[{}] is {}.'.format(w1, NEAR1[w1])) + Path.Log.debug('NEAR0 is {}.'.format(NEAR0)) + Path.Log.debug('NEAR1 is {}.'.format(NEAR1)) """ mainWire = ofstShp.Wires[w0] @@ -1018,7 +1017,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): mainWire, mainWire.Vertexes[vi0], mainWire.Vertexes[vi1] ) except Exception as ee: - PathLog.error("Failed to identify offset edge.\n{}".format(ee)) + Path.Log.error("Failed to identify offset edge.\n{}".format(ee)) return False edgs0 = [] edgs1 = [] @@ -1043,7 +1042,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): def _getOffsetArea(self, obj, fcShape, isHole): """Get an offset area for a shape. Wrapper around PathUtils.getOffsetArea.""" - PathLog.debug("_getOffsetArea()") + Path.Log.debug("_getOffsetArea()") JOB = PathUtils.findParentJob(obj) tolerance = JOB.GeometryTolerance.Value @@ -1057,7 +1056,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): ) def _findNearestVertex(self, shape, point): - PathLog.debug("_findNearestVertex()") + Path.Log.debug("_findNearestVertex()") PT = FreeCAD.Vector(point.x, point.y, 0.0) def sortDist(tup): @@ -1086,7 +1085,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return PNTS def _separateWireAtVertexes(self, wire, VV1, VV2): - PathLog.debug("_separateWireAtVertexes()") + Path.Log.debug("_separateWireAtVertexes()") tolerance = self.JOB.GeometryTolerance.Value grps = [[], []] wireIdxs = [[], []] @@ -1129,7 +1128,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): FLGS[e] += v # Efor - # PathLog.debug('_separateWireAtVertexes() FLGS: {}'.format(FLGS)) + # Path.Log.debug('_separateWireAtVertexes() FLGS: {}'.format(FLGS)) PRE = [] POST = [] @@ -1209,12 +1208,12 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Debugging """ if self.isDebug: - PathLog.debug('grps[0]: {}'.format(grps[0])) - PathLog.debug('grps[1]: {}'.format(grps[1])) - PathLog.debug('wireIdxs[0]: {}'.format(wireIdxs[0])) - PathLog.debug('wireIdxs[1]: {}'.format(wireIdxs[1])) - PathLog.debug('PRE: {}'.format(PRE)) - PathLog.debug('IDXS: {}'.format(IDXS)) + Path.Log.debug('grps[0]: {}'.format(grps[0])) + Path.Log.debug('grps[1]: {}'.format(grps[1])) + Path.Log.debug('wireIdxs[0]: {}'.format(wireIdxs[0])) + Path.Log.debug('wireIdxs[1]: {}'.format(wireIdxs[1])) + Path.Log.debug('PRE: {}'.format(PRE)) + Path.Log.debug('IDXS: {}'.format(IDXS)) """ return (wireIdxs[0], wireIdxs[1]) @@ -1222,7 +1221,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): """_makeCrossSection(shape, sliceZ, zHghtTrgt=None)... Creates cross-section objectc from shape. Translates cross-section to zHghtTrgt if available. Makes face shape from cross-section object. Returns face shape at zHghtTrgt.""" - PathLog.debug("_makeCrossSection()") + Path.Log.debug("_makeCrossSection()") # Create cross-section of shape and translate wires = [] slcs = shape.slice(FreeCAD.Vector(0, 0, 1), sliceZ) @@ -1237,7 +1236,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return False def _makeExtendedBoundBox(self, wBB, bbBfr, zDep): - PathLog.debug("_makeExtendedBoundBox()") + Path.Log.debug("_makeExtendedBoundBox()") p1 = FreeCAD.Vector(wBB.XMin - bbBfr, wBB.YMin - bbBfr, zDep) p2 = FreeCAD.Vector(wBB.XMax + bbBfr, wBB.YMin - bbBfr, zDep) p3 = FreeCAD.Vector(wBB.XMax + bbBfr, wBB.YMax + bbBfr, zDep) @@ -1251,7 +1250,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return Part.Face(Part.Wire([L1, L2, L3, L4])) def _makeIntersectionTags(self, useWire, numOrigEdges, fdv): - PathLog.debug("_makeIntersectionTags()") + Path.Log.debug("_makeIntersectionTags()") # Create circular probe tags around perimiter of wire extTags = [] intTags = [] @@ -1309,7 +1308,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return (begInt, begExt, iTAG, eTAG) def _makeOffsetCircleTag(self, p1, p2, cutterRad, depth, lbl, reverse=False): - # PathLog.debug('_makeOffsetCircleTag()') + # Path.Log.debug('_makeOffsetCircleTag()') pb = FreeCAD.Vector(p1.x, p1.y, 0.0) pe = FreeCAD.Vector(p2.x, p2.y, 0.0) @@ -1344,7 +1343,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): return (intTag, extTag) def _makeStop(self, sType, pA, pB, lbl): - # PathLog.debug('_makeStop()') + # Path.Log.debug('_makeStop()') ofstRad = self.ofstRadius extra = self.radius / 5.0 lng = 0.05 diff --git a/src/Mod/Path/PathScripts/PathSlot.py b/src/Mod/Path/Path/Op/Slot.py similarity index 95% rename from src/Mod/Path/PathScripts/PathSlot.py rename to src/Mod/Path/Path/Op/Slot.py index fac268d809..0c726bdf02 100644 --- a/src/Mod/Path/PathScripts/PathSlot.py +++ b/src/Mod/Path/Path/Op/Slot.py @@ -32,9 +32,8 @@ __contributors__ = "" import FreeCAD from PySide import QtCore import Path -import PathScripts.PathLog as PathLog +import Path.Op.Base as PathOp import PathScripts.PathUtils as PathUtils -import PathScripts.PathOp as PathOp import math # lazily loaded modules @@ -42,7 +41,6 @@ from lazy_loader.lazy_loader import LazyLoader Part = LazyLoader("Part", globals(), "Part") Arcs = LazyLoader("draftgeoutils.arcs", globals(), "draftgeoutils.arcs") -PathGeom = LazyLoader("PathScripts.PathGeom", globals(), "PathScripts.PathGeom") if FreeCAD.GuiUp: FreeCADGui = LazyLoader("FreeCADGui", globals(), "FreeCADGui") @@ -51,10 +49,10 @@ translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectSlot(PathOp.ObjectOp): @@ -81,7 +79,7 @@ class ObjectSlot(PathOp.ObjectOp): self.initOpProperties(obj) # Initialize operation-specific properties # For debugging - if PathLog.getLevel(PathLog.thisModule()) != 4: + if Path.Log.getLevel(Path.Log.thisModule()) != 4: obj.setEditorMode("ShowTempObjects", 2) # hide if not hasattr(obj, "DoNotSetDefaultValues"): @@ -89,7 +87,7 @@ class ObjectSlot(PathOp.ObjectOp): def initOpProperties(self, obj, warn=False): """initOpProperties(obj) ... create operation specific properties""" - PathLog.track() + Path.Log.track() self.addNewProps = list() for (prtyp, nm, grp, tt) in self.opPropertyDefinitions(): @@ -251,7 +249,7 @@ class ObjectSlot(PathOp.ObjectOp): 'raw' is list of (translated_text, data_string) tuples 'translated' is list of translated string literals """ - PathLog.track() + Path.Log.track() enums = { "CutPattern": [ @@ -296,11 +294,11 @@ class ObjectSlot(PathOp.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -354,7 +352,7 @@ class ObjectSlot(PathOp.ObjectOp): in the operation. Returns the updated enumerations dictionary. Existing property values must be stored, and then restored after the assignment of updated enumerations.""" - PathLog.debug("updateEnumerations()") + Path.Log.debug("updateEnumerations()") # Save existing values pre_Ref1 = obj.Reference1 pre_Ref2 = obj.Reference2 @@ -410,7 +408,7 @@ class ObjectSlot(PathOp.ObjectOp): self.initOpProperties(obj, warn=True) self.opApplyPropertyDefaults(obj, job, self.addNewProps) - mode = 2 if PathLog.getLevel(PathLog.thisModule()) != 4 else 0 + mode = 2 if Path.Log.getLevel(Path.Log.thisModule()) != 4 else 0 obj.setEditorMode("ShowTempObjects", mode) # Repopulate enumerations in case of changes @@ -454,11 +452,11 @@ class ObjectSlot(PathOp.ObjectOp): if job: if job.Stock: d = PathUtils.guessDepths(job.Stock.Shape, None) - PathLog.debug("job.Stock exists") + Path.Log.debug("job.Stock exists") else: - PathLog.debug("job.Stock NOT exist") + Path.Log.debug("job.Stock NOT exist") else: - PathLog.debug("job NOT exist") + Path.Log.debug("job NOT exist") if d is not None: obj.OpFinalDepth.Value = d.final_depth @@ -467,8 +465,8 @@ class ObjectSlot(PathOp.ObjectOp): obj.OpFinalDepth.Value = -10 obj.OpStartDepth.Value = 10 - PathLog.debug("Default OpFinalDepth: {}".format(obj.OpFinalDepth.Value)) - PathLog.debug("Default OpStartDepth: {}".format(obj.OpStartDepth.Value)) + Path.Log.debug("Default OpFinalDepth: {}".format(obj.OpFinalDepth.Value)) + Path.Log.debug("Default OpStartDepth: {}".format(obj.OpStartDepth.Value)) def opApplyPropertyLimits(self, obj): """opApplyPropertyLimits(obj) ... Apply necessary limits to user input property values before performing main operation.""" @@ -485,12 +483,12 @@ class ObjectSlot(PathOp.ObjectOp): fbb = base.Shape.getElement(sub).BoundBox zmin = min(zmin, fbb.ZMin) except Part.OCCError as e: - PathLog.error(e) + Path.Log.error(e) obj.OpFinalDepth = zmin def opExecute(self, obj): """opExecute(obj) ... process surface operation""" - PathLog.track() + Path.Log.track() self.base = None self.shape1 = None @@ -509,7 +507,7 @@ class ObjectSlot(PathOp.ObjectOp): self.arcRadius = 0.0 self.newRadius = 0.0 self.featureDetails = ["", ""] - self.isDebug = False if PathLog.getLevel(PathLog.thisModule()) != 4 else True + self.isDebug = False if Path.Log.getLevel(Path.Log.thisModule()) != 4 else True self.showDebugObjects = False self.stockZMin = self.job.Stock.Shape.BoundBox.ZMin CMDS = list() @@ -630,14 +628,14 @@ class ObjectSlot(PathOp.ObjectOp): featureCount = len(subsList) if featureCount == 1: - PathLog.debug("Reference 1: {}".format(obj.Reference1)) + Path.Log.debug("Reference 1: {}".format(obj.Reference1)) sub1 = subsList[0] shape_1 = getattr(base.Shape, sub1) self.shape1 = shape_1 pnts = self._processSingle(obj, shape_1, sub1) else: - PathLog.debug("Reference 1: {}".format(obj.Reference1)) - PathLog.debug("Reference 2: {}".format(obj.Reference2)) + Path.Log.debug("Reference 1: {}".format(obj.Reference1)) + Path.Log.debug("Reference 2: {}".format(obj.Reference2)) sub1 = subsList[0] sub2 = subsList[1] shape_1 = getattr(base.Shape, sub1) @@ -662,16 +660,16 @@ class ObjectSlot(PathOp.ObjectOp): def _finishArc(self, obj, pnts, featureCnt): """This method finishes an Arc Slot operation. It returns the gcode for the slot operation.""" - PathLog.debug("arc center: {}".format(self.arcCenter)) + Path.Log.debug("arc center: {}".format(self.arcCenter)) self._addDebugObject( Part.makeLine(self.arcCenter, self.arcMidPnt), "CentToMidPnt" ) - # PathLog.debug('Pre-offset points are:\np1 = {}\np2 = {}'.format(p1, p2)) + # Path.Log.debug('Pre-offset points are:\np1 = {}\np2 = {}'.format(p1, p2)) if obj.ExtendRadius.Value != 0: # verify offset does not force radius < 0 newRadius = self.arcRadius + obj.ExtendRadius.Value - PathLog.debug( + Path.Log.debug( "arc radius: {}; offset radius: {}".format(self.arcRadius, newRadius) ) if newRadius <= 0: @@ -686,11 +684,11 @@ class ObjectSlot(PathOp.ObjectOp): pnts = self._makeOffsetArc(p1, p2, self.arcCenter, newRadius) self.newRadius = newRadius else: - PathLog.debug("arc radius: {}".format(self.arcRadius)) + Path.Log.debug("arc radius: {}".format(self.arcRadius)) self.newRadius = self.arcRadius # Apply path extension for arcs - # PathLog.debug('Pre-extension points are:\np1 = {}\np2 = {}'.format(p1, p2)) + # Path.Log.debug('Pre-extension points are:\np1 = {}\np2 = {}'.format(p1, p2)) if self.isArc == 1: # Complete circle if obj.ExtendPathStart.Value != 0 or obj.ExtendPathEnd.Value != 0: @@ -712,9 +710,9 @@ class ObjectSlot(PathOp.ObjectOp): return False (p1, p2) = pnts - # PathLog.error('Post-offset points are:\np1 = {}\np2 = {}'.format(p1, p2)) + # Path.Log.error('Post-offset points are:\np1 = {}\np2 = {}'.format(p1, p2)) if self.isDebug: - PathLog.debug("Path Points are:\np1 = {}\np2 = {}".format(p1, p2)) + Path.Log.debug("Path Points are:\np1 = {}\np2 = {}".format(p1, p2)) if p1.sub(p2).Length != 0: self._addDebugObject(Part.makeLine(p1, p2), "Path") @@ -727,7 +725,7 @@ class ObjectSlot(PathOp.ObjectOp): msg += translate("Path_Slot", "operation collides with model.") FreeCAD.Console.PrintError(msg + "\n") - # PathLog.warning('Unable to create G-code. _makeArcGCode() is incomplete.') + # Path.Log.warning('Unable to create G-code. _makeArcGCode() is incomplete.') cmds = self._makeArcGCode(obj, p1, p2) return cmds @@ -790,7 +788,7 @@ class ObjectSlot(PathOp.ObjectOp): ) if self.isDebug: - PathLog.debug("G-code arc command is: {}".format(PATHS[path_index][2])) + Path.Log.debug("G-code arc command is: {}".format(PATHS[path_index][2])) return CMDS @@ -808,7 +806,7 @@ class ObjectSlot(PathOp.ObjectOp): pnts = self._processSingleVertFace(obj, BE) perpZero = False elif self.shapeType1 == "Edge" and self.shapeType2 == "Edge": - PathLog.debug("_finishLine() Perp, featureCnt == 2") + Path.Log.debug("_finishLine() Perp, featureCnt == 2") if perpZero: (p1, p2) = pnts initPerpDist = p1.sub(p2).Length @@ -825,7 +823,7 @@ class ObjectSlot(PathOp.ObjectOp): if self.featureDetails[0] == "arc" and self.featureDetails[1] == "arc": perpZero = False elif self._isParallel(self.dYdX1, self.dYdX2): - PathLog.debug("_finishLine() StE, featureCnt == 2 // edges") + Path.Log.debug("_finishLine() StE, featureCnt == 2 // edges") (p1, p2) = pnts edg1_len = self.shape1.Length edg2_len = self.shape2.Length @@ -862,7 +860,7 @@ class ObjectSlot(PathOp.ObjectOp): (p1, p2) = pnts if self.isDebug: - PathLog.debug("Path Points are:\np1 = {}\np2 = {}".format(p1, p2)) + Path.Log.debug("Path Points are:\np1 = {}\np2 = {}".format(p1, p2)) if p1.sub(p2).Length != 0: self._addDebugObject(Part.makeLine(p1, p2), "Path") @@ -946,9 +944,9 @@ class ObjectSlot(PathOp.ObjectOp): if cat1 == "Face": pnts = False norm = shape_1.normalAt(0.0, 0.0) - PathLog.debug("{}.normalAt(): {}".format(sub1, norm)) + Path.Log.debug("{}.normalAt(): {}".format(sub1, norm)) - if PathGeom.isRoughly(shape_1.BoundBox.ZMax, shape_1.BoundBox.ZMin): + if Path.Geom.isRoughly(shape_1.BoundBox.ZMax, shape_1.BoundBox.ZMin): # Horizontal face if norm.z == 1 or norm.z == -1: pnts = self._processSingleHorizFace(obj, shape_1) @@ -978,7 +976,7 @@ class ObjectSlot(PathOp.ObjectOp): done = True elif cat1 == "Edge": - PathLog.debug("Single edge") + Path.Log.debug("Single edge") pnts = self._processSingleEdge(obj, shape_1) if pnts: (p1, p2) = pnts @@ -998,7 +996,7 @@ class ObjectSlot(PathOp.ObjectOp): def _processSingleHorizFace(self, obj, shape): """Determine slot path endpoints from a single horizontally oriented face.""" - PathLog.debug("_processSingleHorizFace()") + Path.Log.debug("_processSingleHorizFace()") lineTypes = ["Part::GeomLine"] def getRadians(self, E): @@ -1056,19 +1054,19 @@ class ObjectSlot(PathOp.ObjectOp): flag += 1 if debug: msg = "Erroneous Curve.TypeId: {}".format(debug) - PathLog.debug(msg) + Path.Log.debug(msg) pairCnt = len(parallel_edge_pairs) if pairCnt > 1: parallel_edge_pairs.sort(key=lambda tup: tup[0].Length, reverse=True) if self.isDebug: - PathLog.debug(" -pairCnt: {}".format(pairCnt)) + Path.Log.debug(" -pairCnt: {}".format(pairCnt)) for (a, b) in parallel_edge_pairs: - PathLog.debug( + Path.Log.debug( " -pair: {}, {}".format(round(a.Length, 4), round(b.Length, 4)) ) - PathLog.debug(" -parallel_edge_flags: {}".format(parallel_edge_flags)) + Path.Log.debug(" -parallel_edge_flags: {}".format(parallel_edge_flags)) if pairCnt == 0: msg = translate("Path_Slot", "No parallel edges identified.") @@ -1104,7 +1102,7 @@ class ObjectSlot(PathOp.ObjectOp): def _processSingleComplexFace(self, obj, shape): """Determine slot path endpoints from a single complex face.""" - PathLog.debug("_processSingleComplexFace()") + Path.Log.debug("_processSingleComplexFace()") pnts = list() def zVal(p): @@ -1119,7 +1117,7 @@ class ObjectSlot(PathOp.ObjectOp): def _processSingleVertFace(self, obj, shape): """Determine slot path endpoints from a single vertically oriented face with no single bottom edge.""" - PathLog.debug("_processSingleVertFace()") + Path.Log.debug("_processSingleVertFace()") eCnt = len(shape.Edges) V0 = shape.Edges[0].Vertexes[0] V1 = shape.Edges[eCnt - 1].Vertexes[1] @@ -1149,7 +1147,7 @@ class ObjectSlot(PathOp.ObjectOp): def _processSingleEdge(self, obj, edge): """Determine slot path endpoints from a single horizontally oriented edge.""" - PathLog.debug("_processSingleEdge()") + Path.Log.debug("_processSingleEdge()") tolrnc = 0.0000001 lineTypes = ["Part::GeomLine"] curveTypes = ["Part::GeomCircle"] @@ -1180,7 +1178,7 @@ class ObjectSlot(PathOp.ObjectOp): # Circle radius (not used) # r = vP1P2.Length * vP2P3.Length * vP3P1.Length / 2 / l if round(L, 8) == 0.0: - PathLog.error("The three points are colinear, arc is a straight.") + Path.Log.error("The three points are colinear, arc is a straight.") return False # Sphere center. @@ -1205,7 +1203,7 @@ class ObjectSlot(PathOp.ObjectOp): elif edge.Curve.TypeId in curveTypes: if len(edge.Vertexes) == 1: # Circle edge - PathLog.debug("Arc with single vertex.") + Path.Log.debug("Arc with single vertex.") if oversizedTool(edge.BoundBox.XLength): return False @@ -1222,7 +1220,7 @@ class ObjectSlot(PathOp.ObjectOp): self.arcRadius = edge.BoundBox.XLength / 2.0 else: # Arc edge - PathLog.debug("Arc with multiple vertices.") + Path.Log.debug("Arc with multiple vertices.") self.isArc = 2 midPnt = edge.valueAt(edge.getParameterByLength(edge.Length / 2.0)) if not isHorizontal(V1.Z, V2.Z, midPnt.z): @@ -1253,7 +1251,7 @@ class ObjectSlot(PathOp.ObjectOp): def _processDouble(self, obj, shape_1, sub1, shape_2, sub2): """This is the control method for slots based on a two Base Geometry features.""" - PathLog.debug("_processDouble()") + Path.Log.debug("_processDouble()") p1 = None p2 = None @@ -1283,7 +1281,7 @@ class ObjectSlot(PathOp.ObjectOp): # Parallel check for twin face, and face-edge cases if dYdX1 and dYdX2: - PathLog.debug("dYdX1, dYdX2: {}, {}".format(dYdX1, dYdX2)) + Path.Log.debug("dYdX1, dYdX2: {}, {}".format(dYdX1, dYdX2)) if not self._isParallel(dYdX1, dYdX2): if self.shapeType1 != "Edge" or self.shapeType2 != "Edge": msg = translate("Path_Slot", "Selected geometry not parallel.") @@ -1389,7 +1387,7 @@ class ObjectSlot(PathOp.ObjectOp): p = None dYdX = None cat = sub[:4] - PathLog.debug("sub-feature is {}".format(cat)) + Path.Log.debug("sub-feature is {}".format(cat)) Ref = getattr(obj, "Reference" + str(pNum)) if cat == "Face": BE = self._getBottomEdge(shape) @@ -1488,7 +1486,7 @@ class ObjectSlot(PathOp.ObjectOp): 2 * ExtRadians ) # positive Ext lengthens slot so decrease start point angle - # PathLog.debug('begExt angles are: {}, {}'.format(beginRadians, math.degrees(beginRadians))) + # Path.Log.debug('begExt angles are: {}, {}'.format(beginRadians, math.degrees(beginRadians))) chord.rotate(origin, FreeCAD.Vector(0, 0, 1), math.degrees(beginRadians)) chord.translate(self.arcCenter) @@ -1509,7 +1507,7 @@ class ObjectSlot(PathOp.ObjectOp): 2 * ExtRadians ) # negative Ext shortens slot so decrease end point angle - # PathLog.debug('endExt angles are: {}, {}'.format(endRadians, math.degrees(endRadians))) + # Path.Log.debug('endExt angles are: {}, {}'.format(endRadians, math.degrees(endRadians))) chord.rotate(origin, FreeCAD.Vector(0, 0, 1), math.degrees(endRadians)) chord.translate(self.arcCenter) @@ -1773,7 +1771,7 @@ class ObjectSlot(PathOp.ObjectOp): def _makeReference1Enumerations(self, sub, single=False): """Customize Reference1 enumerations based on feature type.""" - PathLog.debug("_makeReference1Enumerations()") + Path.Log.debug("_makeReference1Enumerations()") cat = sub[:4] if single: if cat == "Face": @@ -1789,7 +1787,7 @@ class ObjectSlot(PathOp.ObjectOp): def _makeReference2Enumerations(self, sub): """Customize Reference2 enumerations based on feature type.""" - PathLog.debug("_makeReference2Enumerations()") + Path.Log.debug("_makeReference2Enumerations()") cat = sub[:4] if cat == "Vert": return ["Vertex"] @@ -1859,7 +1857,7 @@ class ObjectSlot(PathOp.ObjectOp): if cmn.Volume > 0.000001: return True except Exception: - PathLog.debug("Failed to complete path collision check.") + Path.Log.debug("Failed to complete path collision check.") return False @@ -1917,7 +1915,7 @@ class ObjectSlot(PathOp.ObjectOp): # verify offset does not force radius < 0 newRadius = arcRadius - rad - # PathLog.debug('arcRadius, newRadius: {}, {}'.format(arcRadius, newRadius)) + # Path.Log.debug('arcRadius, newRadius: {}, {}'.format(arcRadius, newRadius)) if newRadius <= 0: msg = translate( "Path_Slot", "Current offset value produces negative radius." @@ -1931,7 +1929,7 @@ class ObjectSlot(PathOp.ObjectOp): # Arc 2 - outside # verify offset does not force radius < 0 newRadius = arcRadius + rad - # PathLog.debug('arcRadius, newRadius: {}, {}'.format(arcRadius, newRadius)) + # Path.Log.debug('arcRadius, newRadius: {}, {}'.format(arcRadius, newRadius)) if newRadius <= 0: msg = translate( "Path_Slot", "Current offset value produces negative radius." @@ -1975,7 +1973,7 @@ class ObjectSlot(PathOp.ObjectOp): # print("volume=", cmn.Volume) return True except Exception: - PathLog.debug("Failed to complete path collision check.") + Path.Log.debug("Failed to complete path collision check.") return False diff --git a/src/Mod/Path/PathScripts/PathSurface.py b/src/Mod/Path/Path/Op/Surface.py similarity index 97% rename from src/Mod/Path/PathScripts/PathSurface.py rename to src/Mod/Path/Path/Op/Surface.py index 33cf4d92f7..3093e65bd3 100644 --- a/src/Mod/Path/PathScripts/PathSurface.py +++ b/src/Mod/Path/Path/Op/Surface.py @@ -47,9 +47,8 @@ except ImportError: from PySide.QtCore import QT_TRANSLATE_NOOP import Path -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.PathSurfaceSupport as PathSurfaceSupport +import Path.Op.Base as PathOp +import Path.Op.SurfaceSupport as PathSurfaceSupport import PathScripts.PathUtils as PathUtils import math import time @@ -64,10 +63,10 @@ if FreeCAD.GuiUp: if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectSurface(PathOp.ObjectOp): @@ -92,7 +91,7 @@ class ObjectSurface(PathOp.ObjectOp): self.initOpProperties(obj) # Initialize operation-specific properties # For debugging - if PathLog.getLevel(PathLog.thisModule()) != 4: + if Path.Log.getLevel(Path.Log.thisModule()) != 4: obj.setEditorMode("ShowTempObjects", 2) # hide if not hasattr(obj, "DoNotSetDefaultValues"): @@ -603,7 +602,7 @@ class ObjectSurface(PathOp.ObjectOp): self.initOpProperties(obj, warn=True) self.opApplyPropertyDefaults(obj, job, self.addNewProps) - mode = 2 if PathLog.getLevel(PathLog.thisModule()) != 4 else 0 + mode = 2 if Path.Log.getLevel(Path.Log.thisModule()) != 4 else 0 obj.setEditorMode("ShowTempObjects", mode) # Repopulate enumerations in case of changes @@ -645,11 +644,11 @@ class ObjectSurface(PathOp.ObjectOp): if job: if job.Stock: d = PathUtils.guessDepths(job.Stock.Shape, None) - PathLog.debug("job.Stock exists") + Path.Log.debug("job.Stock exists") else: - PathLog.debug("job.Stock NOT exist") + Path.Log.debug("job.Stock NOT exist") else: - PathLog.debug("job NOT exist") + Path.Log.debug("job NOT exist") if d is not None: obj.OpFinalDepth.Value = d.final_depth @@ -658,8 +657,8 @@ class ObjectSurface(PathOp.ObjectOp): obj.OpFinalDepth.Value = -10 obj.OpStartDepth.Value = 10 - PathLog.debug("Default OpFinalDepth: {}".format(obj.OpFinalDepth.Value)) - PathLog.debug("Default OpStartDepth: {}".format(obj.OpStartDepth.Value)) + Path.Log.debug("Default OpFinalDepth: {}".format(obj.OpFinalDepth.Value)) + Path.Log.debug("Default OpStartDepth: {}".format(obj.OpStartDepth.Value)) def opApplyPropertyLimits(self, obj): """opApplyPropertyLimits(obj) ... Apply necessary limits to user input property values before performing main operation.""" @@ -684,20 +683,20 @@ class ObjectSurface(PathOp.ObjectOp): # Limit sample interval if obj.SampleInterval.Value < 0.0001: obj.SampleInterval.Value = 0.0001 - PathLog.error("Sample interval limits are 0.001 to 25.4 millimeters.") + Path.Log.error("Sample interval limits are 0.001 to 25.4 millimeters.") if obj.SampleInterval.Value > 25.4: obj.SampleInterval.Value = 25.4 - PathLog.error("Sample interval limits are 0.001 to 25.4 millimeters.") + Path.Log.error("Sample interval limits are 0.001 to 25.4 millimeters.") # Limit cut pattern angle if obj.CutPatternAngle < -360.0: obj.CutPatternAngle = 0.0 - PathLog.error("Cut pattern angle limits are +-360 degrees.") + Path.Log.error("Cut pattern angle limits are +-360 degrees.") if obj.CutPatternAngle >= 360.0: obj.CutPatternAngle = 0.0 - PathLog.error("Cut pattern angle limits are +- 360 degrees.") + Path.Log.error("Cut pattern angle limits are +- 360 degrees.") # Limit StepOver to natural number percentage if obj.StepOver > 100.0: @@ -708,11 +707,11 @@ class ObjectSurface(PathOp.ObjectOp): # Limit AvoidLastX_Faces to zero and positive values if obj.AvoidLastX_Faces < 0: obj.AvoidLastX_Faces = 0 - PathLog.error("AvoidLastX_Faces: Only zero or positive values permitted.") + Path.Log.error("AvoidLastX_Faces: Only zero or positive values permitted.") if obj.AvoidLastX_Faces > 100: obj.AvoidLastX_Faces = 100 - PathLog.error("AvoidLastX_Faces: Avoid last X faces count limited to 100.") + Path.Log.error("AvoidLastX_Faces: Avoid last X faces count limited to 100.") def opUpdateDepths(self, obj): if hasattr(obj, "Base") and obj.Base: @@ -725,7 +724,7 @@ class ObjectSurface(PathOp.ObjectOp): fbb = base.Shape.getElement(sub).BoundBox zmin = min(zmin, fbb.ZMin) except Part.OCCError as e: - PathLog.error(e) + Path.Log.error(e) obj.OpFinalDepth = zmin elif self.job: if hasattr(obj, "BoundBox"): @@ -741,7 +740,7 @@ class ObjectSurface(PathOp.ObjectOp): def opExecute(self, obj): """opExecute(obj) ... process surface operation""" - PathLog.track() + Path.Log.track() self.modelSTLs = [] self.safeSTLs = [] @@ -771,7 +770,7 @@ class ObjectSurface(PathOp.ObjectOp): self.showDebugObjects = False # Set to true if you want a visual DocObjects created for some path construction objects self.showDebugObjects = obj.ShowTempObjects deleteTempsFlag = True # Set to False for debugging - if PathLog.getLevel(PathLog.thisModule()) == 4: + if Path.Log.getLevel(Path.Log.thisModule()) == 4: deleteTempsFlag = False else: self.showDebugObjects = False @@ -783,7 +782,7 @@ class ObjectSurface(PathOp.ObjectOp): JOB = PathUtils.findParentJob(obj) self.JOB = JOB if JOB is None: - PathLog.error(translate("PathSurface", "No JOB")) + Path.Log.error(translate("PathSurface", "No JOB")) return self.stockZMin = JOB.Stock.Shape.BoundBox.ZMin @@ -803,7 +802,7 @@ class ObjectSurface(PathOp.ObjectOp): oclTool = PathSurfaceSupport.OCL_Tool(ocl, obj) self.cutter = oclTool.getOclTool() if not self.cutter: - PathLog.error( + Path.Log.error( translate( "PathSurface", "Canceling 3D Surface operation. Error creating OCL cutter.", @@ -933,12 +932,12 @@ class ObjectSurface(PathOp.ObjectOp): self.profileShapes = PSF.profileShapes for idx, model in enumerate(JOB.Model.Group): - PathLog.debug(idx) + Path.Log.debug(idx) # Create OCL.stl model objects PathSurfaceSupport._prepareModelSTLs(self, JOB, obj, idx, ocl) if FACES[idx]: - PathLog.debug( + Path.Log.debug( "Working on Model.Group[{}]: {}".format(idx, model.Label) ) if idx > 0: @@ -963,12 +962,12 @@ class ObjectSurface(PathOp.ObjectOp): self._processCutAreas(JOB, obj, idx, FACES[idx], VOIDS[idx]) ) else: - PathLog.debug("No data for model base: {}".format(model.Label)) + Path.Log.debug("No data for model base: {}".format(model.Label)) # Save gcode produced self.commandlist.extend(CMDS) else: - PathLog.error("Failed to pre-process model and/or selected face(s).") + Path.Log.error("Failed to pre-process model and/or selected face(s).") # ###### CLOSING COMMANDS FOR OPERATION ###### @@ -1055,7 +1054,7 @@ class ObjectSurface(PathOp.ObjectOp): """_processCutAreas(JOB, obj, mdlIdx, FCS, VDS)... This method applies any avoided faces or regions to the selected faces. It then calls the correct scan method depending on the ScanType property.""" - PathLog.debug("_processCutAreas()") + Path.Log.debug("_processCutAreas()") final = [] @@ -1108,7 +1107,7 @@ class ObjectSurface(PathOp.ObjectOp): It makes the necessary facial geometries for the actual cut area. It calls the correct Single or Multi-pass method as needed. It returns the gcode for the operation.""" - PathLog.debug("_processPlanarOp()") + Path.Log.debug("_processPlanarOp()") final = [] SCANDATA = [] @@ -1144,14 +1143,14 @@ class ObjectSurface(PathOp.ObjectOp): prflShp = self.profileShapes[mdlIdx][fsi] if prflShp is False: msg = translate("PathSurface", "No profile geometry shape returned.") - PathLog.error(msg) + Path.Log.error(msg) return [] self.showDebugObject(prflShp, "NewProfileShape") # get offset path geometry and perform OCL scan with that geometry pathOffsetGeom = self._offsetFacesToPointData(obj, prflShp) if pathOffsetGeom is False: msg = translate("PathSurface", "No profile path geometry returned.") - PathLog.error(msg) + Path.Log.error(msg) return [] profScan = [self._planarPerformOclScan(obj, pdc, pathOffsetGeom, True)] @@ -1166,7 +1165,7 @@ class ObjectSurface(PathOp.ObjectOp): pathGeom = PGG.generatePathGeometry() if pathGeom is False: msg = translate("PathSurface", "No clearing shape returned.") - PathLog.error(msg) + Path.Log.error(msg) return [] if obj.CutPattern == "Offset": useGeom = self._offsetFacesToPointData(obj, pathGeom, profile=False) @@ -1174,7 +1173,7 @@ class ObjectSurface(PathOp.ObjectOp): msg = translate( "PathSurface", "No clearing path geometry returned." ) - PathLog.error(msg) + Path.Log.error(msg) return [] geoScan = [self._planarPerformOclScan(obj, pdc, useGeom, True)] else: @@ -1194,7 +1193,7 @@ class ObjectSurface(PathOp.ObjectOp): if len(SCANDATA) == 0: msg = translate("PathSurface", "No scan data to convert to Gcode.") - PathLog.error(msg) + Path.Log.error(msg) return [] # Apply depth offset @@ -1230,7 +1229,7 @@ class ObjectSurface(PathOp.ObjectOp): return final def _offsetFacesToPointData(self, obj, subShp, profile=True): - PathLog.debug("_offsetFacesToPointData()") + Path.Log.debug("_offsetFacesToPointData()") offsetLists = [] dist = obj.SampleInterval.Value / 5.0 @@ -1263,7 +1262,7 @@ class ObjectSurface(PathOp.ObjectOp): """_planarPerformOclScan(obj, pdc, pathGeom, offsetPoints=False)... Switching function for calling the appropriate path-geometry to OCL points conversion function for the various cut patterns.""" - PathLog.debug("_planarPerformOclScan()") + Path.Log.debug("_planarPerformOclScan()") SCANS = [] if offsetPoints or obj.CutPattern == "Offset": @@ -1375,7 +1374,7 @@ class ObjectSurface(PathOp.ObjectOp): # Main planar scan functions def _planarDropCutSingle(self, JOB, obj, pdc, safePDC, depthparams, SCANDATA): - PathLog.debug("_planarDropCutSingle()") + Path.Log.debug("_planarDropCutSingle()") GCODE = [Path.Command("N (Beginning of Single-pass layer.)", {})] tolrnc = JOB.GeometryTolerance.Value @@ -1513,7 +1512,7 @@ class ObjectSurface(PathOp.ObjectOp): # lastPrvStpLast = prvStpLast prvStpLast = None lyrDep = depthparams[lyr] - PathLog.debug("Multi-pass lyrDep: {}".format(round(lyrDep, 4))) + Path.Log.debug("Multi-pass lyrDep: {}".format(round(lyrDep, 4))) # Cycle through step-over sections (line segments or arcs) for so in range(0, len(SCANDATA)): @@ -1676,7 +1675,7 @@ class ObjectSurface(PathOp.ObjectOp): prevDepth = lyrDep # Efor - PathLog.debug("Multi-pass op has {} layers (step downs).".format(lyr + 1)) + Path.Log.debug("Multi-pass op has {} layers (step downs).".format(lyr + 1)) return GCODE @@ -1877,9 +1876,9 @@ class ObjectSurface(PathOp.ObjectOp): stepDown = obj.StepDown.Value if hasattr(obj, "StepDown") else 0 rtpd = min(height, p2.z + stepDown + 2) elif not p1: - PathLog.debug("_stepTransitionCmds() p1 is None") + Path.Log.debug("_stepTransitionCmds() p1 is None") elif not p2: - PathLog.debug("_stepTransitionCmds() p2 is None") + Path.Log.debug("_stepTransitionCmds() p2 is None") # Create raise, shift, and optional lower commands if height is not False: @@ -2025,7 +2024,7 @@ class ObjectSurface(PathOp.ObjectOp): return (coPlanar, cmds) def _planarApplyDepthOffset(self, SCANDATA, DepthOffset): - PathLog.debug("Applying DepthOffset value: {}".format(DepthOffset)) + Path.Log.debug("Applying DepthOffset value: {}".format(DepthOffset)) lenScans = len(SCANDATA) for s in range(0, lenScans): SO = SCANDATA[s] # StepOver @@ -2047,7 +2046,7 @@ class ObjectSurface(PathOp.ObjectOp): # Main rotational scan functions def _processRotationalOp(self, JOB, obj, mdlIdx, compoundFaces=None): - PathLog.debug( + Path.Log.debug( "_processRotationalOp(self, JOB, obj, mdlIdx, compoundFaces=None)" ) @@ -2138,7 +2137,7 @@ class ObjectSurface(PathOp.ObjectOp): line ) in scanLines: # extract circular set(ring) of points from scan lines if len(line) != numPnts: - PathLog.debug("Error: line lengths not equal") + Path.Log.debug("Error: line lengths not equal") return rngs for num in range(0, numPnts): @@ -2301,7 +2300,7 @@ class ObjectSurface(PathOp.ObjectOp): prevDepth = layDep lCnt += 1 # increment layer count - PathLog.debug( + Path.Log.debug( "--Layer " + str(lCnt) + ": " @@ -2330,7 +2329,7 @@ class ObjectSurface(PathOp.ObjectOp): # if self.useTiltCutter == True: if obj.CutterTilt != 0.0: cutterOfst = layDep * math.sin(math.radians(obj.CutterTilt)) - PathLog.debug("CutterTilt: cutterOfst is " + str(cutterOfst)) + Path.Log.debug("CutterTilt: cutterOfst is " + str(cutterOfst)) sumAdv = 0.0 for adv in advances: @@ -2686,7 +2685,7 @@ class ObjectSurface(PathOp.ObjectOp): if FR != 0.0: FR += 2.0 - PathLog.debug("ToolType: {}".format(obj.ToolController.Tool.ToolType)) + Path.Log.debug("ToolType: {}".format(obj.ToolController.Tool.ToolType)) if obj.ToolController.Tool.ToolType == "EndMill": # Standard End Mill return ocl.CylCutter(diam_1, (CEH + lenOfst)) @@ -2716,7 +2715,7 @@ class ObjectSurface(PathOp.ObjectOp): return ocl.ConeCutter(diam_1, (CEA / 2), lenOfst) else: # Default to standard end mill - PathLog.warning("Defaulting cutter to standard end mill.") + Path.Log.warning("Defaulting cutter to standard end mill.") return ocl.CylCutter(diam_1, (CEH + lenOfst)) def _getTransitionLine(self, pdc, p1, p2, obj): diff --git a/src/Mod/Path/PathScripts/PathSurfaceSupport.py b/src/Mod/Path/Path/Op/SurfaceSupport.py similarity index 94% rename from src/Mod/Path/PathScripts/PathSurfaceSupport.py rename to src/Mod/Path/Path/Op/SurfaceSupport.py index b81b039f9d..88656ef260 100644 --- a/src/Mod/Path/PathScripts/PathSurfaceSupport.py +++ b/src/Mod/Path/Path/Op/SurfaceSupport.py @@ -29,9 +29,9 @@ __doc__ = "Support functions and classes for 3D Surface and Waterline operations __contributors__ = "" import FreeCAD -import PathScripts.PathLog as PathLog +import Path +import Path.Op.Util as PathOpUtil import PathScripts.PathUtils as PathUtils -import PathScripts.PathOpTools as PathOpTools import math # lazily loaded modules @@ -42,10 +42,10 @@ Part = LazyLoader("Part", globals(), "Part") if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -225,7 +225,7 @@ class PathGeometryGenerator: if minRad < minRadSI: minRad = minRadSI - PathLog.debug(" -centerOfPattern: {}".format(self.centerOfPattern)) + Path.Log.debug(" -centerOfPattern: {}".format(self.centerOfPattern)) # Make small center circle to start pattern if self.obj.StepOver > 50: circle = Part.makeCircle(minRad, self.centerOfPattern) @@ -418,7 +418,7 @@ class PathGeometryGenerator: return FreeCAD.Vector(-1 * x, y, 0.0).add(move) def _extractOffsetFaces(self): - PathLog.debug("_extractOffsetFaces()") + Path.Log.debug("_extractOffsetFaces()") wires = [] shape = self.shape offset = 0.0 # Start right at the edge of cut area @@ -426,7 +426,7 @@ class PathGeometryGenerator: loop_cnt = 0 def _get_direction(w): - if PathOpTools._isWireClockwise(w): + if PathOpUtil._isWireClockwise(w): return 1 return -1 @@ -548,7 +548,7 @@ class ProcessSelectedFaces: self.showDebugObjects = val def preProcessModel(self, module): - PathLog.debug("preProcessModel()") + Path.Log.debug("preProcessModel()") if not self._isReady(module): return False @@ -570,7 +570,7 @@ class ProcessSelectedFaces: # The user has selected subobjects from the base. Pre-Process each. if self.checkBase: - PathLog.debug(" -obj.Base exists. Pre-processing for selected faces.") + Path.Log.debug(" -obj.Base exists. Pre-processing for selected faces.") (hasFace, hasVoid) = self._identifyFacesAndVoids( FACES, VOIDS @@ -591,14 +591,14 @@ class ProcessSelectedFaces: if hasGeometry and not proceed: return False else: - PathLog.debug(" -No obj.Base data.") + Path.Log.debug(" -No obj.Base data.") for m in range(0, lenGRP): self.modelSTLs[m] = True # Process each model base, as a whole, as needed for m in range(0, lenGRP): if self.modelSTLs[m] and not fShapes[m]: - PathLog.debug(" -Pre-processing {} as a whole.".format(GRP[m].Label)) + Path.Log.debug(" -Pre-processing {} as a whole.".format(GRP[m].Label)) if self.obj.BoundBox == "BaseBoundBox": base = GRP[m] elif self.obj.BoundBox == "Stock": @@ -618,24 +618,24 @@ class ProcessSelectedFaces: (fcShp, prflShp) = pPEB if fcShp: if fcShp is True: - PathLog.debug(" -fcShp is True.") + Path.Log.debug(" -fcShp is True.") fShapes[m] = True else: fShapes[m] = [fcShp] if prflShp: if fcShp: - PathLog.debug("vShapes[{}]: {}".format(m, vShapes[m])) + Path.Log.debug("vShapes[{}]: {}".format(m, vShapes[m])) if vShapes[m]: - PathLog.debug(" -Cutting void from base profile shape.") + Path.Log.debug(" -Cutting void from base profile shape.") adjPS = prflShp.cut(vShapes[m][0]) self.profileShapes[m] = [adjPS] else: - PathLog.debug(" -vShapes[m] is False.") + Path.Log.debug(" -vShapes[m] is False.") self.profileShapes[m] = [prflShp] else: - PathLog.debug(" -Saving base profile shape.") + Path.Log.debug(" -Saving base profile shape.") self.profileShapes[m] = [prflShp] - PathLog.debug( + Path.Log.debug( "self.profileShapes[{}]: {}".format( m, self.profileShapes[m] ) @@ -648,21 +648,22 @@ class ProcessSelectedFaces: def _isReady(self, module): """_isReady(module)... Internal method. Checks if required attributes are available for processing obj.Base (the Base Geometry).""" - PathLog.debug("ProcessSelectedFaces _isReady({})".format(module)) - if hasattr(self, module): + Path.Log.debug("ProcessSelectedFaces _isReady({})".format(module)) + modMethodName = module.replace("Op.", "Path") + if hasattr(self, modMethodName): self.module = module - modMethod = getattr(self, module) # gets the attribute only + modMethod = getattr(self, modMethodName) # gets the attribute only modMethod() # executes as method else: - PathLog.error('PSF._isReady() no "{}" method.'.format(module)) + Path.Log.error('PSF._isReady() no "{}" method.'.format(module)) return False if not self.radius: - PathLog.error("PSF._isReady() no cutter radius available.") + Path.Log.error("PSF._isReady() no cutter radius available.") return False if not self.depthParams: - PathLog.error("PSF._isReady() no depth params available.") + Path.Log.error("PSF._isReady() no depth params available.") return False return True @@ -698,13 +699,13 @@ class ProcessSelectedFaces: if F[m] is False: F[m] = [] F[m].append((shape, faceIdx)) - PathLog.debug(".. Cutting {}".format(sub)) + Path.Log.debug(".. Cutting {}".format(sub)) hasFace = True else: if V[m] is False: V[m] = [] V[m].append((shape, faceIdx)) - PathLog.debug(".. Avoiding {}".format(sub)) + Path.Log.debug(".. Avoiding {}".format(sub)) hasVoid = True return (hasFace, hasVoid) @@ -718,7 +719,7 @@ class ProcessSelectedFaces: isHole = False if self.obj.HandleMultipleFeatures == "Collectively": cont = True - PathLog.debug("Attempting to get cross-section of collective faces.") + Path.Log.debug("Attempting to get cross-section of collective faces.") outFCS, ifL = self.findUnifiedRegions(FCS) if self.obj.InternalFeaturesCut and ifL: ifL = [] # clear avoid shape list @@ -732,7 +733,7 @@ class ProcessSelectedFaces: # Handle profile edges request if cont and self.profileEdges != "None": - PathLog.debug(".. include Profile Edge") + Path.Log.debug(".. include Profile Edge") ofstVal = self._calculateOffsetValue(isHole) psOfst = PathUtils.getOffsetArea(cfsL, ofstVal, plane=self.wpc) if psOfst: @@ -763,7 +764,7 @@ class ProcessSelectedFaces: lenIfL = len(ifL) if not self.obj.InternalFeaturesCut: if lenIfL == 0: - PathLog.debug(" -No internal features saved.") + Path.Log.debug(" -No internal features saved.") else: if lenIfL == 1: casL = ifL[0] @@ -798,7 +799,7 @@ class ProcessSelectedFaces: ifL = [] # avoid shape list if outerFace: - PathLog.debug( + Path.Log.debug( "Attempting to create offset face of Face{}".format(fNum) ) @@ -854,7 +855,7 @@ class ProcessSelectedFaces: mVS.append(ifs) if VDS: - PathLog.debug("Processing avoid faces.") + Path.Log.debug("Processing avoid faces.") cont = True isHole = False @@ -928,7 +929,7 @@ class ProcessSelectedFaces: partshape=base.Shape, subshape=None, depthparams=self.depthParams ) # Produces .Shape except Exception as ee: - PathLog.error(str(ee)) + Path.Log.error(str(ee)) shell = base.Shape.Shells[0] solid = Part.makeSolid(shell) try: @@ -936,7 +937,7 @@ class ProcessSelectedFaces: partshape=solid, subshape=None, depthparams=self.depthParams ) # Produces .Shape except Exception as eee: - PathLog.error(str(eee)) + Path.Log.error(str(eee)) cont = False if cont: @@ -946,11 +947,11 @@ class ProcessSelectedFaces: if csFaceShape is False: csFaceShape = getSliceFromEnvelope(baseEnv) if csFaceShape is False: - PathLog.debug("Failed to slice baseEnv shape.") + Path.Log.debug("Failed to slice baseEnv shape.") cont = False if cont and self.profileEdges != "None": - PathLog.debug(" -Attempting profile geometry for model base.") + Path.Log.debug(" -Attempting profile geometry for model base.") ofstVal = self._calculateOffsetValue(isHole) psOfst = PathUtils.getOffsetArea(csFaceShape, ofstVal, plane=self.wpc) if psOfst: @@ -966,7 +967,7 @@ class ProcessSelectedFaces: csFaceShape, ofstVal, plane=self.wpc ) if faceOffsetShape is False: - PathLog.debug("getOffsetArea() failed for entire base.") + Path.Log.debug("getOffsetArea() failed for entire base.") else: faceOffsetShape.translate( FreeCAD.Vector(0.0, 0.0, 0.0 - faceOffsetShape.BoundBox.ZMin) @@ -1005,7 +1006,7 @@ class ProcessSelectedFaces: def findUnifiedRegions(self, shapeAndIndexTuples, useAreaImplementation=True): """Wrapper around area and wire based region unification implementations.""" - PathLog.debug("findUnifiedRegions()") + Path.Log.debug("findUnifiedRegions()") # Allow merging of faces within the LinearDeflection tolerance. tolerance = self.obj.LinearDeflection.Value # Default: normal to Z=1 (XY plane), at Z=0 @@ -1038,7 +1039,7 @@ class ProcessSelectedFaces: internalFaces = Part.makeCompound(internalFaces) return ([outlineShape], [internalFaces]) except Exception as e: - PathLog.warning( + Path.Log.warning( "getOffsetArea failed: {}; Using FindUnifiedRegions.".format(e) ) # Use face-unifying class @@ -1053,14 +1054,14 @@ class ProcessSelectedFaces: # Functions for getting a shape envelope and cross-section def getExtrudedShape(wire): - PathLog.debug("getExtrudedShape()") + Path.Log.debug("getExtrudedShape()") wBB = wire.BoundBox extFwd = math.floor(2.0 * wBB.ZLength) + 10.0 try: shell = wire.extrude(FreeCAD.Vector(0.0, 0.0, extFwd)) except Exception as ee: - PathLog.error(" -extrude wire failed: \n{}".format(ee)) + Path.Log.error(" -extrude wire failed: \n{}".format(ee)) return False SHP = Part.makeSolid(shell) @@ -1068,7 +1069,7 @@ def getExtrudedShape(wire): def getShapeSlice(shape): - PathLog.debug("getShapeSlice()") + Path.Log.debug("getShapeSlice()") bb = shape.BoundBox mid = (bb.ZMin + bb.ZMax) / 2.0 @@ -1096,7 +1097,7 @@ def getShapeSlice(shape): if slcArea < midArea: for W in slcShp.Wires: if W.isClosed() is False: - PathLog.debug(" -wire.isClosed() is False") + Path.Log.debug(" -wire.isClosed() is False") return False if len(slcShp.Wires) == 1: wire = slcShp.Wires[0] @@ -1118,7 +1119,7 @@ def getShapeSlice(shape): def getProjectedFace(tempGroup, wire): import Draft - PathLog.debug("getProjectedFace()") + Path.Log.debug("getProjectedFace()") F = FreeCAD.ActiveDocument.addObject("Part::Feature", "tmpProjectionWire") F.Shape = wire F.purgeTouched() @@ -1129,7 +1130,7 @@ def getProjectedFace(tempGroup, wire): prj.purgeTouched() tempGroup.addObject(prj) except Exception as ee: - PathLog.error(str(ee)) + Path.Log.error(str(ee)) return False else: pWire = Part.Wire(prj.Shape.Edges) @@ -1141,7 +1142,7 @@ def getProjectedFace(tempGroup, wire): def getCrossSection(shape): - PathLog.debug("getCrossSection()") + Path.Log.debug("getCrossSection()") wires = [] bb = shape.BoundBox mid = (bb.ZMin + bb.ZMax) / 2.0 @@ -1154,19 +1155,19 @@ def getCrossSection(shape): comp.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - comp.BoundBox.ZMin)) csWire = comp.Wires[0] if csWire.isClosed() is False: - PathLog.debug(" -comp.Wires[0] is not closed") + Path.Log.debug(" -comp.Wires[0] is not closed") return False CS = Part.Face(csWire) CS.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - CS.BoundBox.ZMin)) return CS else: - PathLog.debug(" -No wires from .slice() method") + Path.Log.debug(" -No wires from .slice() method") return False def getShapeEnvelope(shape): - PathLog.debug("getShapeEnvelope()") + Path.Log.debug("getShapeEnvelope()") wBB = shape.BoundBox extFwd = wBB.ZLength + 10.0 @@ -1187,7 +1188,7 @@ def getShapeEnvelope(shape): def getSliceFromEnvelope(env): - PathLog.debug("getSliceFromEnvelope()") + Path.Log.debug("getSliceFromEnvelope()") eBB = env.BoundBox extFwd = eBB.ZLength + 10.0 maxz = eBB.ZMin + extFwd @@ -1217,7 +1218,7 @@ def _makeSafeSTL(self, JOB, obj, mdlIdx, faceShapes, voidShapes, ocl): Creates and OCL.stl object with combined data with waste stock, model, and avoided faces. Travel lines can be checked against this STL object to determine minimum travel height to clear stock and model.""" - PathLog.debug("_makeSafeSTL()") + Path.Log.debug("_makeSafeSTL()") fuseShapes = [] Mdl = JOB.Model.Group[mdlIdx] @@ -1243,7 +1244,7 @@ def _makeSafeSTL(self, JOB, obj, mdlIdx, faceShapes, voidShapes, ocl): ) # Produces .Shape cont = True except Exception as ee: - PathLog.error(str(ee)) + Path.Log.error(str(ee)) shell = Mdl.Shape.Shells[0] solid = Part.makeSolid(shell) try: @@ -1252,7 +1253,7 @@ def _makeSafeSTL(self, JOB, obj, mdlIdx, faceShapes, voidShapes, ocl): ) # Produces .Shape cont = True except Exception as eee: - PathLog.error(str(eee)) + Path.Log.error(str(eee)) if cont: stckWst = JOB.Stock.Shape.cut(envBB) @@ -1330,7 +1331,7 @@ def _makeSTL(model, obj, ocl, model_type=None): def pathGeomToLinesPointSet(self, obj, compGeoShp): """pathGeomToLinesPointSet(self, obj, compGeoShp)... Convert a compound set of sequential line segments to directionally-oriented collinear groupings.""" - PathLog.debug("pathGeomToLinesPointSet()") + Path.Log.debug("pathGeomToLinesPointSet()") # Extract intersection line segments for return value as [] LINES = [] inLine = [] @@ -1426,9 +1427,9 @@ def pathGeomToLinesPointSet(self, obj, compGeoShp): isEven = lnCnt % 2 if isEven == 0: - PathLog.debug("Line count is ODD: {}.".format(lnCnt)) + Path.Log.debug("Line count is ODD: {}.".format(lnCnt)) else: - PathLog.debug("Line count is even: {}.".format(lnCnt)) + Path.Log.debug("Line count is even: {}.".format(lnCnt)) return LINES @@ -1437,7 +1438,7 @@ def pathGeomToZigzagPointSet(self, obj, compGeoShp): """_pathGeomToZigzagPointSet(self, obj, compGeoShp)... Convert a compound set of sequential line segments to directionally-oriented collinear groupings with a ZigZag directional indicator included for each collinear group.""" - PathLog.debug("_pathGeomToZigzagPointSet()") + Path.Log.debug("_pathGeomToZigzagPointSet()") # Extract intersection line segments for return value as [] LINES = [] inLine = [] @@ -1516,9 +1517,9 @@ def pathGeomToZigzagPointSet(self, obj, compGeoShp): # Fix directional issue with LAST line when line count is even isEven = lnCnt % 2 if isEven == 0: # Changed to != with 90 degree CutPatternAngle - PathLog.debug("Line count is even: {}.".format(lnCnt)) + Path.Log.debug("Line count is even: {}.".format(lnCnt)) else: - PathLog.debug("Line count is ODD: {}.".format(lnCnt)) + Path.Log.debug("Line count is ODD: {}.".format(lnCnt)) dirFlg = -1 * dirFlg if not obj.CutPatternReversed: if self.CutClimb: @@ -1561,7 +1562,7 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): Convert a compound set of arcs/circles to a set of directionally-oriented arc end points and the corresponding center point.""" # Extract intersection line segments for return value as [] - PathLog.debug("pathGeomToCircularPointSet()") + Path.Log.debug("pathGeomToCircularPointSet()") ARCS = [] stpOvrEI = [] segEI = [] @@ -1668,7 +1669,7 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): for so in range(0, len(stpOvrEI)): SO = stpOvrEI[so] if SO[0] == "L": # L = Loop/Ring/Circle - # PathLog.debug("SO[0] == 'Loop'") + # Path.Log.debug("SO[0] == 'Loop'") lei = SO[1] # loop Edges index v1 = compGeoShp.Edges[lei].Vertexes[0] @@ -1703,7 +1704,7 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): ) # OCL.Arc(firstPnt, lastPnt, centerPnt, dir=True(CCW direction)) ARCS.append(("L", dirFlg, [arc])) elif SO[0] == "A": # A = Arc - # PathLog.debug("SO[0] == 'Arc'") + # Path.Log.debug("SO[0] == 'Arc'") PRTS = [] EI = SO[1] # list of corresponding Edges indexes CONN = SO[2] # list of corresponding connected edges tuples (iE, iS) @@ -1803,7 +1804,7 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): def pathGeomToSpiralPointSet(obj, compGeoShp): """_pathGeomToSpiralPointSet(obj, compGeoShp)... Convert a compound set of sequential line segments to directional, connected groupings.""" - PathLog.debug("_pathGeomToSpiralPointSet()") + Path.Log.debug("_pathGeomToSpiralPointSet()") # Extract intersection line segments for return value as [] LINES = [] inLine = [] @@ -1856,7 +1857,7 @@ def pathGeomToSpiralPointSet(obj, compGeoShp): def pathGeomToOffsetPointSet(obj, compGeoShp): """pathGeomToOffsetPointSet(obj, compGeoShp)... Convert a compound set of 3D profile segmented wires to 2D segments, applying linear optimization.""" - PathLog.debug("pathGeomToOffsetPointSet()") + Path.Log.debug("pathGeomToOffsetPointSet()") LINES = [] optimize = obj.OptimizeLinearPaths @@ -1952,7 +1953,7 @@ class FindUnifiedRegions: base = ef.cut(cutBox) if base.Volume == 0: - PathLog.debug( + Path.Log.debug( "Ignoring Face{}. It is likely vertical with no horizontal exposure.".format( fcIdx ) @@ -2026,7 +2027,7 @@ class FindUnifiedRegions: count[1] += 1 def _groupEdgesByLength(self): - PathLog.debug("_groupEdgesByLength()") + Path.Log.debug("_groupEdgesByLength()") threshold = self.geomToler grp = [] processLast = False @@ -2074,7 +2075,7 @@ class FindUnifiedRegions: self.idGroups.append(grp) def _identifySharedEdgesByLength(self, grp): - PathLog.debug("_identifySharedEdgesByLength()") + Path.Log.debug("_identifySharedEdgesByLength()") holds = [] specialIndexes = [] threshold = self.geomToler @@ -2132,7 +2133,7 @@ class FindUnifiedRegions: self.noSharedEdges = False def _extractWiresFromEdges(self): - PathLog.debug("_extractWiresFromEdges()") + Path.Log.debug("_extractWiresFromEdges()") DATA = self.edgeData holds = [] firstEdge = None @@ -2229,7 +2230,7 @@ class FindUnifiedRegions: # Ewhile numLoops = len(LOOPS) - PathLog.debug(" -numLoops: {}.".format(numLoops)) + Path.Log.debug(" -numLoops: {}.".format(numLoops)) if numLoops > 0: for li in range(0, numLoops): Edges = LOOPS[li] @@ -2258,7 +2259,7 @@ class FindUnifiedRegions: self.REGIONS.sort(key=faceArea, reverse=True) def _identifyInternalFeatures(self): - PathLog.debug("_identifyInternalFeatures()") + Path.Log.debug("_identifyInternalFeatures()") remList = [] for (top, fcIdx) in self.topFaces: @@ -2273,14 +2274,14 @@ class FindUnifiedRegions: remList.append(s) break else: - PathLog.debug(" - No common area.\n") + Path.Log.debug(" - No common area.\n") remList.sort(reverse=True) for ri in remList: self.REGIONS.pop(ri) def _processNestedRegions(self): - PathLog.debug("_processNestedRegions()") + Path.Log.debug("_processNestedRegions()") cont = True hold = [] Ids = [] @@ -2325,7 +2326,7 @@ class FindUnifiedRegions: # Accessory methods def _getCompleteCrossSection(self, shape): - PathLog.debug("_getCompleteCrossSection()") + Path.Log.debug("_getCompleteCrossSection()") wires = [] bb = shape.BoundBox mid = (bb.ZMin + bb.ZMax) / 2.0 @@ -2339,7 +2340,7 @@ class FindUnifiedRegions: CS.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - CS.BoundBox.ZMin)) return CS - PathLog.debug(" -No wires from .slice() method") + Path.Log.debug(" -No wires from .slice() method") return False def _edgesAreConnected(self, e1, e2): @@ -2382,7 +2383,7 @@ class FindUnifiedRegions: def getUnifiedRegions(self): """getUnifiedRegions()... Returns a list of unified regions from list of tuples (faceShape, faceIndex) received at instantiation of the class object.""" - PathLog.debug("getUnifiedRegions()") + Path.Log.debug("getUnifiedRegions()") if len(self.FACES) == 0: msg = "No FACE data tuples received at instantiation of class.\n" FreeCAD.Console.PrintError(msg) @@ -2431,7 +2432,7 @@ class FindUnifiedRegions: self._identifySharedEdgesByLength(grp) if self.noSharedEdges: - PathLog.debug("No shared edges by length detected.") + Path.Log.debug("No shared edges by length detected.") allTopFaces = [] for (topFace, fcIdx) in self.topFaces: allTopFaces.append(topFace) @@ -2473,8 +2474,8 @@ class FindUnifiedRegions: class OCL_Tool: - """The OCL_Tool class is designed to translate a FreeCAD standard ToolBit shape, - or Legacy tool type, in the active Tool Controller, into an OCL tool type.""" + """The OCL_Tool class is designed to translate a FreeCAD standard ToolBit shape + in the active Tool Controller, into an OCL tool type.""" def __init__(self, ocl, obj, safe=False): self.ocl = ocl @@ -2501,11 +2502,8 @@ class OCL_Tool: if hasattr(self.tool, "ShapeName"): self.toolType = self.tool.ShapeName # Indicates ToolBit tool self.toolMode = "ToolBit" - elif hasattr(self.tool, "ToolType"): - self.toolType = self.tool.ToolType # Indicates Legacy tool - self.toolMode = "Legacy" if self.toolType: - PathLog.debug( + Path.Log.debug( "OCL_Tool tool mode, type: {}, {}".format(self.toolMode, self.toolType) ) @@ -2726,25 +2724,7 @@ class OCL_Tool: def _setToolMethod(self): toolMap = dict() - if self.toolMode == "Legacy": - # Set cutter details - # https://www.freecadweb.org/api/dd/dfe/classPath_1_1Tool.html#details - toolMap = { - "EndMill": "CylCutter", - "BallEndMill": "BallCutter", - "SlotCutter": "CylCutter", - "Engraver": "ConeCutter", - "Drill": "ConeCutter", - "CounterSink": "ConeCutter", - "FlyCutter": "CylCutter", - "CenterDrill": "None", - "CounterBore": "None", - "Reamer": "None", - "Tap": "None", - "ChamferMill": "None", - "CornerRound": "None", - } - elif self.toolMode == "ToolBit": + if self.toolMode == "ToolBit": toolMap = { "endmill": "CylCutter", "ballend": "BallCutter", @@ -2780,7 +2760,7 @@ class OCL_Tool: FreeCAD.Console.PrintError(err + "\n") return False else: - PathLog.debug("OCL_Tool tool method: {}".format(self.toolMethod)) + Path.Log.debug("OCL_Tool tool method: {}".format(self.toolMethod)) oclToolMethod = getattr(self, "_ocl" + self.toolMethod) oclToolMethod() @@ -2812,7 +2792,7 @@ class OCL_Tool: # Support functions def makeExtendedBoundBox(wBB, bbBfr, zDep): - PathLog.debug("makeExtendedBoundBox()") + Path.Log.debug("makeExtendedBoundBox()") p1 = FreeCAD.Vector(wBB.XMin - bbBfr, wBB.YMin - bbBfr, zDep) p2 = FreeCAD.Vector(wBB.XMax + bbBfr, wBB.YMin - bbBfr, zDep) p3 = FreeCAD.Vector(wBB.XMax + bbBfr, wBB.YMax + bbBfr, zDep) diff --git a/src/Mod/Path/PathScripts/PathThreadMilling.py b/src/Mod/Path/Path/Op/ThreadMilling.py similarity index 93% rename from src/Mod/Path/PathScripts/PathThreadMilling.py rename to src/Mod/Path/Path/Op/ThreadMilling.py index 6aa1a67de7..144098273a 100644 --- a/src/Mod/Path/PathScripts/PathThreadMilling.py +++ b/src/Mod/Path/Path/Op/ThreadMilling.py @@ -24,11 +24,9 @@ from __future__ import print_function import FreeCAD import Path -import PathScripts.PathCircularHoleBase as PathCircularHoleBase -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import Generators.threadmilling_generator as threadmilling +import Path.Base.Generator.threadmilling as threadmilling +import Path.Op.Base as PathOp +import Path.Op.CircularHoleBase as PathCircularHoleBase import math from PySide.QtCore import QT_TRANSLATE_NOOP @@ -41,10 +39,10 @@ __doc__ = "Path thread milling operation." SQRT_3_DIVIDED_BY_2 = 0.8660254037844386 if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -106,7 +104,7 @@ def _isThreadInternal(obj): return obj.ThreadType in ThreadTypesInternal def threadSetupInternal(obj, zTop, zBottom): - PathLog.track() + Path.Log.track() if obj.ThreadOrientation == RightHand: # Right hand thread, G2, top down -> conventional milling if obj.Direction == DirectionConventional: @@ -121,7 +119,7 @@ def threadSetupInternal(obj, zTop, zBottom): return ("G2", zBottom, zTop) def threadSetupExternal(obj, zTop, zBottom): - PathLog.track() + Path.Log.track() if obj.ThreadOrientation == RightHand: # right hand thread, G2, top down -> climb milling if obj.Direction == DirectionClimb: @@ -136,7 +134,7 @@ def threadSetupExternal(obj, zTop, zBottom): def threadSetup(obj): """Return (cmd, zbegin, zend) of thread milling operation""" - PathLog.track() + Path.Log.track() zTop = obj.StartDepth.Value zBottom = obj.FinalDepth.Value @@ -149,7 +147,7 @@ def threadSetup(obj): def threadRadii(internal, majorDia, minorDia, toolDia, toolCrest): """threadRadii(majorDia, minorDia, toolDia, toolCrest) ... returns the minimum and maximum radius for thread.""" - PathLog.track(internal, majorDia, minorDia, toolDia, toolCrest) + Path.Log.track(internal, majorDia, minorDia, toolDia, toolCrest) if toolCrest is None: toolCrest = 0.0 # As it turns out metric and imperial standard threads follow the same rules. @@ -171,12 +169,12 @@ def threadRadii(internal, majorDia, minorDia, toolDia, toolCrest): # Compensate for the crest of the tool toolTip = innerTip - toolCrest * SQRT_3_DIVIDED_BY_2 radii = ((majorDia + toolDia) / 2.0, toolTip + toolDia / 2.0) - PathLog.track(radii) + Path.Log.track(radii) return radii def threadPasses(count, radii, internal, majorDia, minorDia, toolDia, toolCrest): - PathLog.track(count, radii, internal, majorDia, minorDia, toolDia, toolCrest) + Path.Log.track(count, radii, internal, majorDia, minorDia, toolDia, toolCrest) # the logic goes as follows, total area to be removed: # A = H * W ... where H is the depth and W is half the width of a thread # H = k * sin(30) = k * 1/2 -> k = 2 * H @@ -198,7 +196,7 @@ def threadPasses(count, radii, internal, majorDia, minorDia, toolDia, toolCrest) # the order in which they have to get milled. As a result H ends up being negative # and the math for internal and external threads is identical. passes = [minor + h for h in Hi] - PathLog.debug(f"threadPasses({minor}, {major}) -> H={H} : {Hi} --> {passes}") + Path.Log.debug(f"threadPasses({minor}, {major}) -> H={H} : {Hi} --> {passes}") return passes @@ -210,7 +208,7 @@ def elevatorRadius(obj, center, internal, tool): dy = float(obj.MinorDiameter - tool.Diameter) / 2 - 1 if dy < 0: if obj.MinorDiameter < tool.Diameter: - PathLog.error( + Path.Log.error( "The selected tool is too big (d={}) for milling a thread with minor diameter D={}".format( tool.Diameter, obj.MinorDiameter ) @@ -235,7 +233,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): 'raw' is list of (translated_text, data_string) tuples 'translated' is list of translated string literals """ - PathLog.track() + Path.Log.track() # Enumeration lists for App::PropertyEnumeration properties enums = { @@ -305,20 +303,20 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data def circularHoleFeatures(self, obj): - PathLog.track() + Path.Log.track() return PathOp.FeatureBaseGeometry def initCircularHoleOperation(self, obj): - PathLog.track() + Path.Log.track() obj.addProperty( "App::PropertyEnumeration", "ThreadOrientation", @@ -414,7 +412,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): setattr(obj, n[0], n[1]) def threadPassRadii(self, obj): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) rMajor = (obj.MajorDiameter.Value - self.tool.Diameter) / 2.0 rMinor = (obj.MinorDiameter.Value - self.tool.Diameter) / 2.0 if obj.Passes < 1: @@ -426,7 +424,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): return list(reversed(passes)) def executeThreadMill(self, obj, loc, gcode, zStart, zFinal, pitch): - PathLog.track(obj.Label, loc, gcode, zStart, zFinal, pitch) + Path.Log.track(obj.Label, loc, gcode, zStart, zFinal, pitch) elevator = elevatorRadius(obj, loc, _isThreadInternal(obj), self.tool) move2clearance = Path.Command( @@ -480,7 +478,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): ) def circularHoleExecute(self, obj, holes): - PathLog.track() + Path.Log.track() if self.isToolSupported(obj, self.tool): self.commandlist.append(Path.Command("(Begin Thread Milling)")) @@ -489,7 +487,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): if obj.TPI > 0: pitch = 25.4 / obj.TPI if pitch <= 0: - PathLog.error("Cannot create thread with pitch {}".format(pitch)) + Path.Log.error("Cannot create thread with pitch {}".format(pitch)) return # rapid to clearance height @@ -503,10 +501,10 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): pitch, ) else: - PathLog.error("No suitable Tool found for thread milling operation") + Path.Log.error("No suitable Tool found for thread milling operation") def opSetDefaultValues(self, obj, job): - PathLog.track() + Path.Log.track() obj.ThreadOrientation = RightHand obj.ThreadType = ThreadTypeMetricInternal6H obj.ThreadFit = 50 @@ -519,7 +517,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): def isToolSupported(self, obj, tool): """Thread milling only supports thread milling cutters.""" support = hasattr(tool, "Diameter") and hasattr(tool, "Crest") - PathLog.track(tool.Label, support) + Path.Log.track(tool.Label, support) return support diff --git a/src/Mod/Path/PathScripts/PathOpTools.py b/src/Mod/Path/Path/Op/Util.py similarity index 90% rename from src/Mod/Path/PathScripts/PathOpTools.py rename to src/Mod/Path/Path/Op/Util.py index 3a5c530f2f..b201b0a447 100644 --- a/src/Mod/Path/PathScripts/PathOpTools.py +++ b/src/Mod/Path/Path/Op/Util.py @@ -23,8 +23,7 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog +import Path import math # lazily loaded modules @@ -32,7 +31,7 @@ from lazy_loader.lazy_loader import LazyLoader Part = LazyLoader("Part", globals(), "Part") -__title__ = "PathOpTools - Tools for Path operations." +__title__ = "Util - Utility functions for Path operations." __author__ = "sliptonic (Brad Collette)" __url__ = "https://www.freecadweb.org" __doc__ = "Collection of functions used by various Path operations. The functions are specific to Path and the algorithms employed by Path's operations." @@ -41,10 +40,10 @@ __doc__ = "Collection of functions used by various Path operations. The function PrintWireDebug = False if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -109,26 +108,26 @@ def debugWire(label, w): def _orientEdges(inEdges): """_orientEdges(inEdges) ... internal worker function to orient edges so the last vertex of one edge connects to the first vertex of the next edge. Assumes the edges are in an order so they can be connected.""" - PathLog.track() + Path.Log.track() # orient all edges of the wire so each edge's last value connects to the next edge's first value e0 = inEdges[0] # well, even the very first edge could be misoriented, so let's try and connect it to the second if 1 < len(inEdges): last = e0.valueAt(e0.LastParameter) e1 = inEdges[1] - if not PathGeom.pointsCoincide( + if not Path.Geom.pointsCoincide( last, e1.valueAt(e1.FirstParameter) - ) and not PathGeom.pointsCoincide(last, e1.valueAt(e1.LastParameter)): + ) and not Path.Geom.pointsCoincide(last, e1.valueAt(e1.LastParameter)): debugEdge("# _orientEdges - flip first", e0) - e0 = PathGeom.flipEdge(e0) + e0 = Path.Geom.flipEdge(e0) edges = [e0] last = e0.valueAt(e0.LastParameter) for e in inEdges[1:]: edge = ( e - if PathGeom.pointsCoincide(last, e.valueAt(e.FirstParameter)) - else PathGeom.flipEdge(e) + if Path.Geom.pointsCoincide(last, e.valueAt(e.FirstParameter)) + else Path.Geom.flipEdge(e) ) edges.append(edge) last = edge.valueAt(edge.LastParameter) @@ -153,7 +152,7 @@ def _isWireClockwise(w): v0 = e.valueAt(e.FirstParameter) v1 = e.valueAt(e.LastParameter) area = area + (v0.x * v1.y - v1.x * v0.y) - PathLog.track(area) + Path.Log.track(area) return area < 0 @@ -167,13 +166,13 @@ def orientWire(w, forward=True): If forward = True (the default) the wire is oriented clockwise, looking down the negative Z axis. If forward = False the wire is oriented counter clockwise. If forward = None the orientation is determined by the order in which the edges appear in the wire.""" - PathLog.debug("orienting forward: {}: {} edges".format(forward, len(w.Edges))) + Path.Log.debug("orienting forward: {}: {} edges".format(forward, len(w.Edges))) wire = Part.Wire(_orientEdges(w.Edges)) if forward is not None: if forward != _isWireClockwise(wire): - PathLog.track("orientWire - needs flipping") - return PathGeom.flipWire(wire) - PathLog.track("orientWire - ok") + Path.Log.track("orientWire - needs flipping") + return Path.Geom.flipWire(wire) + Path.Log.track("orientWire - ok") return wire @@ -182,7 +181,7 @@ def offsetWire(wire, base, offset, forward, Side=None): The function tries to avoid most of the pitfalls of Part.makeOffset2D which is possible because all offsetting happens in the XY plane. """ - PathLog.track("offsetWire") + Path.Log.track("offsetWire") if 1 == len(wire.Edges): edge = wire.Edges[0] @@ -196,7 +195,7 @@ def offsetWire(wire, base, offset, forward, Side=None): curve.Radius + offset, curve.Center, FreeCAD.Vector(0, 0, z) ) if base.isInside(new_edge.Vertexes[0].Point, offset / 2, True): - if offset > curve.Radius or PathGeom.isRoughly(offset, curve.Radius): + if offset > curve.Radius or Path.Geom.isRoughly(offset, curve.Radius): # offsetting a hole by its own radius (or more) makes the hole vanish return None if Side: @@ -285,9 +284,9 @@ def offsetWire(wire, base, offset, forward, Side=None): # flip the edge if it's not on the right side of the original edge if forward is not None: v1 = edge.Vertexes[1].Point - p0 - left = PathGeom.Side.Left == PathGeom.Side.of(v0, v1) + left = Path.Geom.Side.Left == Path.Geom.Side.of(v0, v1) if left != forward: - edge = PathGeom.flipEdge(edge) + edge = Path.Geom.flipEdge(edge) return Part.Wire([edge]) # if we get to this point the assumption is that makeOffset2D can deal with the edge @@ -297,11 +296,11 @@ def offsetWire(wire, base, offset, forward, Side=None): if wire.isClosed(): if not base.isInside(owire.Edges[0].Vertexes[0].Point, offset / 2, True): - PathLog.track("closed - outside") + Path.Log.track("closed - outside") if Side: Side[0] = "Outside" return orientWire(owire, forward) - PathLog.track("closed - inside") + Path.Log.track("closed - inside") if Side: Side[0] = "Inside" try: @@ -342,7 +341,7 @@ def offsetWire(wire, base, offset, forward, Side=None): p0 = edge.firstVertex().Point p1 = edge.lastVertex().Point for p in insideEndpoints: - if PathGeom.pointsCoincide(p, p0, 0.01) or PathGeom.pointsCoincide( + if Path.Geom.pointsCoincide(p, p0, 0.01) or Path.Geom.pointsCoincide( p, p1, 0.01 ): return True @@ -361,7 +360,7 @@ def offsetWire(wire, base, offset, forward, Side=None): def isCircleAt(edge, center): """isCircleAt(edge, center) ... helper function returns True if edge is a circle at the given center.""" if Part.Circle == type(edge.Curve) or Part.ArcOfCircle == type(edge.Curve): - return PathGeom.pointsCoincide(edge.Curve.Center, center) + return Path.Geom.pointsCoincide(edge.Curve.Center, center) return False # split offset wire into edges to the left side and edges to the right side @@ -376,7 +375,7 @@ def offsetWire(wire, base, offset, forward, Side=None): # next side, we're done for e in owire.Edges + owire.Edges: if isCircleAt(e, start): - if PathGeom.pointsCoincide(e.Curve.Axis, FreeCAD.Vector(0, 0, 1)): + if Path.Geom.pointsCoincide(e.Curve.Axis, FreeCAD.Vector(0, 0, 1)): if not collectLeft and leftSideEdges: break collectLeft = True @@ -387,7 +386,7 @@ def offsetWire(wire, base, offset, forward, Side=None): collectLeft = False collectRight = True elif isCircleAt(e, end): - if PathGeom.pointsCoincide(e.Curve.Axis, FreeCAD.Vector(0, 0, 1)): + if Path.Geom.pointsCoincide(e.Curve.Axis, FreeCAD.Vector(0, 0, 1)): if not collectRight and rightSideEdges: break collectLeft = False @@ -410,20 +409,20 @@ def offsetWire(wire, base, offset, forward, Side=None): edges = leftSideEdges for e in longestWire.Edges: for e0 in rightSideEdges: - if PathGeom.edgesMatch(e, e0): + if Path.Geom.edgesMatch(e, e0): edges = rightSideEdges - PathLog.debug("#use right side edges") + Path.Log.debug("#use right side edges") if not forward: - PathLog.debug("#reverse") + Path.Log.debug("#reverse") edges.reverse() return orientWire(Part.Wire(edges), None) # at this point we have the correct edges and they are in the order for forward # traversal (climb milling). If that's not what we want just reverse the order, # orientWire takes care of orienting the edges appropriately. - PathLog.debug("#use left side edges") + Path.Log.debug("#use left side edges") if not forward: - PathLog.debug("#reverse") + Path.Log.debug("#reverse") edges.reverse() return orientWire(Part.Wire(edges), None) diff --git a/src/Mod/Path/PathScripts/PathVcarve.py b/src/Mod/Path/Path/Op/Vcarve.py similarity index 94% rename from src/Mod/Path/PathScripts/PathVcarve.py rename to src/Mod/Path/Path/Op/Vcarve.py index 31b5377ced..15d98d7017 100644 --- a/src/Mod/Path/PathScripts/PathVcarve.py +++ b/src/Mod/Path/Path/Op/Vcarve.py @@ -23,12 +23,9 @@ import FreeCAD import Part import Path -import PathScripts.PathEngraveBase as PathEngraveBase -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp +import Path.Op.Base as PathOp +import Path.Op.EngraveBase as PathEngraveBase import PathScripts.PathUtils as PathUtils -import PathScripts.PathGeom as PathGeom -import PathScripts.PathPreferences as PathPreferences import math from PySide.QtCore import QT_TRANSLATE_NOOP @@ -46,10 +43,10 @@ TWIN = 5 BORDERLINE = 6 if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -181,7 +178,7 @@ def _calculate_depth(MIC, geom): # given a maximum inscribed circle (MIC) and tool angle, # return depth of cut relative to zStart. depth = geom.start - round(MIC * geom.scale, 4) - PathLog.debug("zStart value: {} depth: {}".format(geom.start, depth)) + Path.Log.debug("zStart value: {} depth: {}".format(geom.start, depth)) return max(depth, geom.stop) @@ -246,7 +243,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): ) obj.Colinear = 10.0 obj.Discretize = 0.01 - obj.Tolerance = PathPreferences.defaultGeometryTolerance() + obj.Tolerance = Path.Preferences.defaultGeometryTolerance() self.setupAdditionalProperties(obj) def opOnDocumentRestored(self, obj): @@ -264,7 +261,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): def insert_many_wires(vd, wires): for wire in wires: - PathLog.debug("discretize value: {}".format(obj.Discretize)) + Path.Log.debug("discretize value: {}".format(obj.Discretize)) pts = wire.discretize(QuasiDeflection=obj.Discretize) ptv = [FreeCAD.Vector(p.x, p.y) for p in pts] ptv.append(ptv[0]) @@ -286,7 +283,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): Path.Command("G1 X{} Y{} Z{} F{}".format(p.x, p.y, p.z, vSpeed)) ) for e in edges: - path.extend(PathGeom.cmdsForEdge(e, hSpeed=hSpeed, vSpeed=vSpeed)) + path.extend(Path.Geom.cmdsForEdge(e, hSpeed=hSpeed, vSpeed=vSpeed)) return path @@ -336,10 +333,10 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): def opExecute(self, obj): """opExecute(obj) ... process engraving operation""" - PathLog.track() + Path.Log.track() if not hasattr(obj.ToolController.Tool, "CuttingEdgeAngle"): - PathLog.error( + Path.Log.error( translate( "Path_Vcarve", "VCarve requires an engraving cutter with CuttingEdgeAngle", @@ -347,7 +344,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): ) if obj.ToolController.Tool.CuttingEdgeAngle >= 180.0: - PathLog.error( + Path.Log.error( translate( "Path_Vcarve", "Engraver Cutting Edge Angle must be < 180 degrees." ) @@ -376,7 +373,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if faces: self.buildPathMedial(obj, faces) else: - PathLog.error( + Path.Log.error( translate( "PathVcarve", "The Job Base Object has no engraveable element. Engraving operation will produce no output.", @@ -384,7 +381,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): ) except Exception as e: - PathLog.error( + Path.Log.error( "Error processing Base object. Engraving operation will produce no output." ) diff --git a/src/Mod/Path/PathScripts/PathWaterline.py b/src/Mod/Path/Path/Op/Waterline.py similarity index 96% rename from src/Mod/Path/PathScripts/PathWaterline.py rename to src/Mod/Path/Path/Op/Waterline.py index 83db68725c..96f742c12e 100644 --- a/src/Mod/Path/PathScripts/PathWaterline.py +++ b/src/Mod/Path/Path/Op/Waterline.py @@ -43,9 +43,8 @@ except ImportError: raise ImportError import Path -import PathScripts.PathLog as PathLog -import PathScripts.PathOp as PathOp -import PathScripts.PathSurfaceSupport as PathSurfaceSupport +import Path.Op.Base as PathOp +import Path.Op.SurfaceSupport as PathSurfaceSupport import PathScripts.PathUtils as PathUtils import math import time @@ -60,10 +59,10 @@ if FreeCAD.GuiUp: import FreeCADGui if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class ObjectWaterline(PathOp.ObjectOp): @@ -145,11 +144,11 @@ class ObjectWaterline(PathOp.ObjectOp): data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -161,7 +160,7 @@ class ObjectWaterline(PathOp.ObjectOp): self.initOpProperties(obj) # Initialize operation-specific properties # For debugging - if PathLog.getLevel(PathLog.thisModule()) != 4: + if Path.Log.getLevel(Path.Log.thisModule()) != 4: obj.setEditorMode("ShowTempObjects", 2) # hide if not hasattr(obj, "DoNotSetDefaultValues"): @@ -575,7 +574,7 @@ class ObjectWaterline(PathOp.ObjectOp): self.initOpProperties(obj, warn=True) self.opApplyPropertyDefaults(obj, job, self.addNewProps) - mode = 2 if PathLog.getLevel(PathLog.thisModule()) != 4 else 0 + mode = 2 if Path.Log.getLevel(Path.Log.thisModule()) != 4 else 0 obj.setEditorMode("ShowTempObjects", mode) # Repopulate enumerations in case of changes @@ -620,11 +619,11 @@ class ObjectWaterline(PathOp.ObjectOp): if job.Stock: d = PathUtils.guessDepths(job.Stock.Shape, None) obj.IgnoreOuterAbove = job.Stock.Shape.BoundBox.ZMax + 0.000001 - PathLog.debug("job.Stock exists") + Path.Log.debug("job.Stock exists") else: - PathLog.debug("job.Stock NOT exist") + Path.Log.debug("job.Stock NOT exist") else: - PathLog.debug("job NOT exist") + Path.Log.debug("job NOT exist") if d is not None: obj.OpFinalDepth.Value = d.final_depth @@ -633,15 +632,15 @@ class ObjectWaterline(PathOp.ObjectOp): obj.OpFinalDepth.Value = -10 obj.OpStartDepth.Value = 10 - PathLog.debug("Default OpFinalDepth: {}".format(obj.OpFinalDepth.Value)) - PathLog.debug("Default OpStartDepth: {}".format(obj.OpStartDepth.Value)) + Path.Log.debug("Default OpFinalDepth: {}".format(obj.OpFinalDepth.Value)) + Path.Log.debug("Default OpStartDepth: {}".format(obj.OpStartDepth.Value)) def opApplyPropertyLimits(self, obj): """opApplyPropertyLimits(obj) ... Apply necessary limits to user input property values before performing main operation.""" # Limit sample interval if obj.SampleInterval.Value < 0.0001: obj.SampleInterval.Value = 0.0001 - PathLog.error( + Path.Log.error( translate( "PathWaterline", "Sample interval limits are 0.0001 to 25.4 millimeters.", @@ -649,7 +648,7 @@ class ObjectWaterline(PathOp.ObjectOp): ) if obj.SampleInterval.Value > 25.4: obj.SampleInterval.Value = 25.4 - PathLog.error( + Path.Log.error( translate( "PathWaterline", "Sample interval limits are 0.0001 to 25.4 millimeters.", @@ -659,14 +658,14 @@ class ObjectWaterline(PathOp.ObjectOp): # Limit cut pattern angle if obj.CutPatternAngle < -360.0: obj.CutPatternAngle = 0.0 - PathLog.error( + Path.Log.error( translate( "PathWaterline", "Cut pattern angle limits are +-360 degrees." ) ) if obj.CutPatternAngle >= 360.0: obj.CutPatternAngle = 0.0 - PathLog.error( + Path.Log.error( translate( "PathWaterline", "Cut pattern angle limits are +- 360 degrees." ) @@ -681,7 +680,7 @@ class ObjectWaterline(PathOp.ObjectOp): # Limit AvoidLastX_Faces to zero and positive values if obj.AvoidLastX_Faces < 0: obj.AvoidLastX_Faces = 0 - PathLog.error( + Path.Log.error( translate( "PathWaterline", "AvoidLastX_Faces: Only zero or positive values permitted.", @@ -689,7 +688,7 @@ class ObjectWaterline(PathOp.ObjectOp): ) if obj.AvoidLastX_Faces > 100: obj.AvoidLastX_Faces = 100 - PathLog.error( + Path.Log.error( translate( "PathWaterline", "AvoidLastX_Faces: Avoid last X faces count limited to 100.", @@ -707,7 +706,7 @@ class ObjectWaterline(PathOp.ObjectOp): fbb = base.Shape.getElement(sub).BoundBox zmin = min(zmin, fbb.ZMin) except Part.OCCError as e: - PathLog.error(e) + Path.Log.error(e) obj.OpFinalDepth = zmin elif self.job: if hasattr(obj, "BoundBox"): @@ -723,7 +722,7 @@ class ObjectWaterline(PathOp.ObjectOp): def opExecute(self, obj): """opExecute(obj) ... process surface operation""" - PathLog.track() + Path.Log.track() self.modelSTLs = list() self.safeSTLs = list() @@ -756,19 +755,19 @@ class ObjectWaterline(PathOp.ObjectOp): self.showDebugObjects = False # Set to true if you want a visual DocObjects created for some path construction objects self.showDebugObjects = obj.ShowTempObjects deleteTempsFlag = True # Set to False for debugging - if PathLog.getLevel(PathLog.thisModule()) == 4: + if Path.Log.getLevel(Path.Log.thisModule()) == 4: deleteTempsFlag = False else: self.showDebugObjects = False # mark beginning of operation and identify parent Job - PathLog.info("\nBegin Waterline operation...") + Path.Log.info("\nBegin Waterline operation...") startTime = time.time() # Identify parent Job JOB = PathUtils.findParentJob(obj) if JOB is None: - PathLog.error(translate("PathWaterline", "No JOB")) + Path.Log.error(translate("PathWaterline", "No JOB")) return self.stockZMin = JOB.Stock.Shape.BoundBox.ZMin @@ -788,7 +787,7 @@ class ObjectWaterline(PathOp.ObjectOp): oclTool = PathSurfaceSupport.OCL_Tool(ocl, obj) self.cutter = oclTool.getOclTool() if not self.cutter: - PathLog.error( + Path.Log.error( translate( "PathWaterline", "Canceling Waterline operation. Error creating OCL cutter.", @@ -871,16 +870,14 @@ class ObjectWaterline(PathOp.ObjectOp): if self.geoTlrnc == 0.0: useDGT = True except AttributeError as ee: - PathLog.warning( - "{}\nPlease set Job.GeometryTolerance to an acceptable value. Using PathPreferences.defaultGeometryTolerance().".format( + Path.Log.warning( + "{}\nPlease set Job.GeometryTolerance to an acceptable value. Using Path.Preferences.defaultGeometryTolerance().".format( ee ) ) useDGT = True if useDGT: - import PathScripts.PathPreferences as PathPreferences - - self.geoTlrnc = PathPreferences.defaultGeometryTolerance() + self.geoTlrnc = Path.Preferences.defaultGeometryTolerance() # Calculate default depthparams for operation self.depthParams = PathUtils.depth_params( @@ -929,7 +926,7 @@ class ObjectWaterline(PathOp.ObjectOp): pPM = PSF.preProcessModel(self.module) # Process selected faces, if available if pPM is False: - PathLog.error("Unable to pre-process obj.Base.") + Path.Log.error("Unable to pre-process obj.Base.") else: (FACES, VOIDS) = pPM self.modelSTLs = PSF.modelSTLs @@ -942,7 +939,7 @@ class ObjectWaterline(PathOp.ObjectOp): Mdl = JOB.Model.Group[m] if FACES[m] is False: - PathLog.error( + Path.Log.error( "No data for model base: {}".format(JOB.Model.Group[m].Label) ) else: @@ -959,7 +956,7 @@ class ObjectWaterline(PathOp.ObjectOp): {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}, ) ) - PathLog.info( + Path.Log.info( "Working on Model.Group[{}]: {}".format(m, Mdl.Label) ) # make stock-model-voidShapes STL model for avoidance detection on transitions @@ -1038,7 +1035,7 @@ class ObjectWaterline(PathOp.ObjectOp): execTime = time.time() - startTime msg = translate("PathWaterline", "operation time is") - PathLog.info("Waterline " + msg + " {} sec.".format(execTime)) + Path.Log.info("Waterline " + msg + " {} sec.".format(execTime)) return True @@ -1047,7 +1044,7 @@ class ObjectWaterline(PathOp.ObjectOp): """_processWaterlineAreas(JOB, obj, mdlIdx, FCS, VDS)... This method applies any avoided faces or regions to the selected faces. It then calls the correct method.""" - PathLog.debug("_processWaterlineAreas()") + Path.Log.debug("_processWaterlineAreas()") final = list() @@ -1111,7 +1108,7 @@ class ObjectWaterline(PathOp.ObjectOp): """_getExperimentalWaterlinePaths(PNTSET, csHght, cutPattern)... Switching function for calling the appropriate path-geometry to OCL points conversion function for the various cut patterns.""" - PathLog.debug("_getExperimentalWaterlinePaths()") + Path.Log.debug("_getExperimentalWaterlinePaths()") SCANS = list() # PNTSET is list, by stepover. @@ -1300,7 +1297,7 @@ class ObjectWaterline(PathOp.ObjectOp): pntsPerLine = len(scanLines[0]) msg = "--OCL scan: " + str(lenSL * pntsPerLine) + " points, with " msg += str(numScanLines) + " lines and " + str(pntsPerLine) + " pts/line" - PathLog.debug(msg) + Path.Log.debug(msg) # Extract Wl layers per depthparams lyr = 0 @@ -1311,7 +1308,7 @@ class ObjectWaterline(PathOp.ObjectOp): cmds = self._getWaterline(obj, scanLines, layDep, lyr, lenSL, pntsPerLine) commands.extend(cmds) lyr += 1 - PathLog.debug( + Path.Log.debug( "--All layer scans combined took " + str(time.time() - layTime) + " s" ) return commands @@ -1581,7 +1578,7 @@ class ObjectWaterline(PathOp.ObjectOp): while srch is True: srch = False if srchCnt > maxSrchs: - PathLog.debug( + Path.Log.debug( "Max search scans, " + str(maxSrchs) + " reached\nPossible incomplete waterline result!" @@ -1597,7 +1594,7 @@ class ObjectWaterline(PathOp.ObjectOp): self.topoMap[L][P] = 0 # Mute the starting point loopList.append(loop) srchCnt += 1 - PathLog.debug( + Path.Log.debug( "Search count for layer " + str(lyr) + " is " @@ -1620,7 +1617,7 @@ class ObjectWaterline(PathOp.ObjectOp): while follow is True: ptc += 1 if ptc > ptLmt: - PathLog.debug( + Path.Log.debug( "Loop number " + str(loopNum) + " at [" @@ -1729,7 +1726,7 @@ class ObjectWaterline(PathOp.ObjectOp): def _experimentalWaterlineOp(self, JOB, obj, mdlIdx, subShp=None): """_waterlineOp(JOB, obj, mdlIdx, subShp=None) ... Main waterline function to perform waterline extraction from model.""" - PathLog.debug("_experimentalWaterlineOp()") + Path.Log.debug("_experimentalWaterlineOp()") commands = [] base = JOB.Model.Group[mdlIdx] @@ -1751,7 +1748,7 @@ class ObjectWaterline(PathOp.ObjectOp): depthparams = [finDep] else: depthparams = [dp for dp in depthParams] - PathLog.debug("Experimental Waterline depthparams:\n{}".format(depthparams)) + Path.Log.debug("Experimental Waterline depthparams:\n{}".format(depthparams)) # Prepare PathDropCutter objects with STL data # safePDC = self._planarGetPDC(safeSTL, depthparams[lenDP - 1], obj.SampleInterval.Value, self.cutter) @@ -1777,7 +1774,7 @@ class ObjectWaterline(PathOp.ObjectOp): base.Shape, depthparams, bbFace, trimFace, borderFace ) if not CUTAREAS: - PathLog.error("No cross-section cut areas identified.") + Path.Log.error("No cross-section cut areas identified.") return commands caCnt = 0 @@ -1799,7 +1796,7 @@ class ObjectWaterline(PathOp.ObjectOp): self.showDebugObject(area, "CutArea_{}".format(caCnt)) else: data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString - PathLog.debug("Cut area at {} is zero.".format(data)) + Path.Log.debug("Cut area at {} is zero.".format(data)) # get offset wire(s) based upon cross-section cut area if cont: @@ -1811,7 +1808,7 @@ class ObjectWaterline(PathOp.ObjectOp): data = FreeCAD.Units.Quantity( csHght, FreeCAD.Units.Length ).UserString - PathLog.debug( + Path.Log.debug( "No offset area returned for cut area depth at {}.".format(data) ) cont = False @@ -1828,7 +1825,7 @@ class ObjectWaterline(PathOp.ObjectOp): data = FreeCAD.Units.Quantity( csHght, FreeCAD.Units.Length ).UserString - PathLog.error( + Path.Log.error( "Could not determine solid faces at {}.".format(data) ) else: @@ -1836,7 +1833,7 @@ class ObjectWaterline(PathOp.ObjectOp): if cont: data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString - PathLog.debug("... Clearning area at {}.".format(data)) + Path.Log.debug("... Clearning area at {}.".format(data)) # Make waterline path for current CUTAREA depth (csHght) commands.extend(self._wiresToWaterlinePath(obj, clearArea, csHght)) clearArea.translate( @@ -1863,7 +1860,7 @@ class ObjectWaterline(PathOp.ObjectOp): # Efor if clearLastLayer and obj.ClearLastLayer != "Off": - PathLog.debug("... Clearning last layer") + Path.Log.debug("... Clearning last layer") (clrLyr, cLL) = self._clearLayer(obj, 1, 1, False) lastClearArea.translate( FreeCAD.Vector(0.0, 0.0, 0.0 - lastClearArea.BoundBox.ZMin) @@ -1885,7 +1882,7 @@ class ObjectWaterline(PathOp.ObjectOp): """_getCutAreas(JOB, shape, depthparams, bbFace, borderFace) ... Takes shape, depthparams and base-envelope-cross-section, and returns a list of cut areas - one for each depth.""" - PathLog.debug("_getCutAreas()") + Path.Log.debug("_getCutAreas()") CUTAREAS = list() isFirst = True @@ -1894,7 +1891,7 @@ class ObjectWaterline(PathOp.ObjectOp): # Cycle through layer depths for dp in range(0, lenDP): csHght = depthparams[dp] - # PathLog.debug('Depth {} is {}'.format(dp + 1, csHght)) + # Path.Log.debug('Depth {} is {}'.format(dp + 1, csHght)) # Get slice at depth of shape csFaces = self._getModelCrossSection(shape, csHght) # returned at Z=0.0 @@ -1922,7 +1919,7 @@ class ObjectWaterline(PathOp.ObjectOp): CUTAREAS.append(cutArea) isFirst = False else: - PathLog.error("No waterline at depth: {} mm.".format(csHght)) + Path.Log.error("No waterline at depth: {} mm.".format(csHght)) # Efor if len(CUTAREAS) > 0: @@ -1931,7 +1928,7 @@ class ObjectWaterline(PathOp.ObjectOp): return False def _wiresToWaterlinePath(self, obj, ofstPlnrShp, csHght): - PathLog.debug("_wiresToWaterlinePath()") + Path.Log.debug("_wiresToWaterlinePath()") commands = list() # Translate path geometry to layer height @@ -1965,7 +1962,7 @@ class ObjectWaterline(PathOp.ObjectOp): return commands def _makeCutPatternLayerPaths(self, JOB, obj, clrAreaShp, csHght, cutPattern): - PathLog.debug("_makeCutPatternLayerPaths()") + Path.Log.debug("_makeCutPatternLayerPaths()") commands = [] clrAreaShp.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - clrAreaShp.BoundBox.ZMin)) @@ -1981,7 +1978,7 @@ class ObjectWaterline(PathOp.ObjectOp): self.tmpCOM = PGG.getCenterOfPattern() pathGeom = PGG.generatePathGeometry() if not pathGeom: - PathLog.warning("No path geometry generated.") + Path.Log.warning("No path geometry generated.") return commands pathGeom.translate( FreeCAD.Vector(0.0, 0.0, csHght - pathGeom.BoundBox.ZMin) @@ -2013,7 +2010,7 @@ class ObjectWaterline(PathOp.ObjectOp): return commands def _makeOffsetLayerPaths(self, obj, clrAreaShp, csHght): - PathLog.debug("_makeOffsetLayerPaths()") + Path.Log.debug("_makeOffsetLayerPaths()") cmds = list() ofst = 0.0 - self.cutOut shape = clrAreaShp @@ -2029,14 +2026,14 @@ class ObjectWaterline(PathOp.ObjectOp): if cnt == 0: ofst = 0.0 - self.cutOut cnt += 1 - PathLog.debug( + Path.Log.debug( " -Offset path count: {} at height: {}".format(cnt, round(csHght, 2)) ) return cmds def _clearGeomToPaths(self, JOB, obj, safePDC, stpOVRS, cutPattern): - PathLog.debug("_clearGeomToPaths()") + Path.Log.debug("_clearGeomToPaths()") GCODE = [Path.Command("N (Beginning of Single-pass layer.)", {})] tolrnc = JOB.GeometryTolerance.Value @@ -2083,7 +2080,7 @@ class ObjectWaterline(PathOp.ObjectOp): # Cycle through current step-over parts for i in range(0, lenPRTS): prt = PRTS[i] - # PathLog.debug('prt: {}'.format(prt)) + # Path.Log.debug('prt: {}'.format(prt)) if prt == "BRK": nxtStart = PRTS[i + 1][0] # minSTH = self._getMinSafeTravelHeight(safePDC, last, nxtStart) # Check safe travel height against fullSTL @@ -2115,7 +2112,7 @@ class ObjectWaterline(PathOp.ObjectOp): elif cutPattern in ["Circular", "CircularZigZag"]: # isCircle = True if lenPRTS == 1 else False isZigZag = True if cutPattern == "CircularZigZag" else False - PathLog.debug( + Path.Log.debug( "so, isZigZag, odd, cMode: {}, {}, {}, {}".format( so, isZigZag, odd, prt[3] ) @@ -2135,11 +2132,11 @@ class ObjectWaterline(PathOp.ObjectOp): return GCODE def _getSolidAreasFromPlanarFaces(self, csFaces): - PathLog.debug("_getSolidAreasFromPlanarFaces()") + Path.Log.debug("_getSolidAreasFromPlanarFaces()") holds = list() useFaces = list() lenCsF = len(csFaces) - PathLog.debug("lenCsF: {}".format(lenCsF)) + Path.Log.debug("lenCsF: {}".format(lenCsF)) if lenCsF == 1: useFaces = csFaces @@ -2204,7 +2201,7 @@ class ObjectWaterline(PathOp.ObjectOp): return False def _getModelCrossSection(self, shape, csHght): - PathLog.debug("_getModelCrossSection()") + Path.Log.debug("_getModelCrossSection()") wires = list() def byArea(fc): @@ -2224,7 +2221,7 @@ class ObjectWaterline(PathOp.ObjectOp): FCS.sort(key=byArea, reverse=True) return FCS else: - PathLog.debug(" -No wires from .slice() method") + Path.Log.debug(" -No wires from .slice() method") return False @@ -2256,7 +2253,7 @@ class ObjectWaterline(PathOp.ObjectOp): def _wireToPath(self, obj, wire, startVect): """_wireToPath(obj, wire, startVect) ... wire to path.""" - PathLog.track() + Path.Log.track() paths = [] pathParams = {} @@ -2336,7 +2333,7 @@ class ObjectWaterline(PathOp.ObjectOp): return cmds def _clearLayer(self, obj, ca, lastCA, clearLastLayer): - PathLog.debug("_clearLayer()") + Path.Log.debug("_clearLayer()") clrLyr = False if obj.ClearLastLayer == "Off": @@ -2345,7 +2342,7 @@ class ObjectWaterline(PathOp.ObjectOp): else: obj.CutPattern = "None" if ca == lastCA: # if current iteration is last layer - PathLog.debug("... Clearing bottom layer.") + Path.Log.debug("... Clearing bottom layer.") clrLyr = obj.ClearLastLayer clearLastLayer = False diff --git a/src/Mod/Path/Path/Op/__init__.py b/src/Mod/Path/Path/Op/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/PathPost.py b/src/Mod/Path/Path/Post/Command.py similarity index 89% rename from src/Mod/Path/PathScripts/PathPost.py rename to src/Mod/Path/Path/Post/Command.py index e89ccc6224..324412c415 100644 --- a/src/Mod/Path/PathScripts/PathPost.py +++ b/src/Mod/Path/Path/Post/Command.py @@ -27,26 +27,24 @@ from __future__ import print_function import FreeCAD import FreeCADGui import Path -import PathScripts.PathJob as PathJob -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathUtil as PathUtil +import Path.Base.Util as PathUtil +import Path.Main.Job as PathJob import PathScripts.PathUtils as PathUtils import os import re -from PathScripts.PathPostProcessor import PostProcessor +from Path.Post.Processor import PostProcessor from PySide import QtCore, QtGui from datetime import datetime from PySide.QtCore import QT_TRANSLATE_NOOP -LOG_MODULE = PathLog.thisModule() +LOG_MODULE = Path.Log.thisModule() -if True: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) +if False: + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -70,7 +68,7 @@ def processFileNameSubstitutions( """Process any substitutions in the outputpath or filename.""" # The following section allows substitution within the path part - PathLog.track(f"path before substitution: {outputpath}") + Path.Log.track(f"path before substitution: {outputpath}") if "%D" in outputpath: # Directory of active document D = FreeCAD.ActiveDocument.FileName @@ -100,10 +98,10 @@ def processFileNameSubstitutions( j = job.Label outputpath = outputpath.replace("%j", j) - PathLog.track(f"path after substitution: {outputpath}") + Path.Log.track(f"path after substitution: {outputpath}") # The following section allows substitution within the filename part - PathLog.track(f"filename before substitution: {filename}") + Path.Log.track(f"filename before substitution: {filename}") # Use the file label if "%d" in filename: @@ -122,7 +120,7 @@ def processFileNameSubstitutions( # This section handles unique names for splitting output if job.SplitOutput: - PathLog.track() + Path.Log.track() if "%T" in filename and job.OrderOutputBy == "Tool": filename = filename.replace("%T", subpartname) @@ -142,26 +140,26 @@ def processFileNameSubstitutions( else: filename = f"{filename}-{sequencenumber}" - PathLog.track(f"filename after substitution: {filename}") + Path.Log.track(f"filename after substitution: {filename}") if not ext: ext = ".nc" - PathLog.track(f"file extension: {ext}") + Path.Log.track(f"file extension: {ext}") fullPath = f"{outputpath}{os.path.sep}{filename}{ext}" - PathLog.track(f"full filepath: {fullPath}") + Path.Log.track(f"full filepath: {fullPath}") return fullPath def resolveFileName(job, subpartname, sequencenumber): - PathLog.track(subpartname, sequencenumber) + Path.Log.track(subpartname, sequencenumber) validPathSubstitutions = ["D", "d", "M", "j"] validFilenameSubstitutions = ["j", "d", "T", "t", "W", "O", "S"] # Look for preference default - outputpath, filename = os.path.split(PathPreferences.defaultOutputFile()) + outputpath, filename = os.path.split(Path.Preferences.defaultOutputFile()) filename, ext = os.path.splitext(filename) # Override with document default if it exists @@ -198,7 +196,7 @@ def resolveFileName(job, subpartname, sequencenumber): ext = ".nc" # By now we should have a sanitized path, filename and extension to work with - PathLog.track(f"path: {outputpath} name: {filename} ext: {ext}") + Path.Log.track(f"path: {outputpath} name: {filename} ext: {ext}") fullPath = processFileNameSubstitutions( job, @@ -210,7 +208,7 @@ def resolveFileName(job, subpartname, sequencenumber): ) # This section determines whether user interaction is necessary - policy = PathPreferences.defaultOutputPolicy() + policy = Path.Preferences.defaultOutputPolicy() openDialog = policy == "Open File Dialog" # if os.path.isdir(filename) or not os.path.isdir(os.path.dirname(filename)): @@ -238,7 +236,7 @@ def resolveFileName(job, subpartname, sequencenumber): if openDialog: foo = QtGui.QFileDialog.getSaveFileName( - QtGui.QApplication.activeWindow(), "Output File", fullPath + QtGui.QApplication.activeWindow(), "Output File", filename ) if foo[0]: fullPath = foo[0] @@ -250,9 +248,8 @@ def resolveFileName(job, subpartname, sequencenumber): for s in validPathSubstitutions + validFilenameSubstitutions: fullPath = fullPath.replace(f"%{s}", "") - fullPath = os.path.normpath(fullPath) - PathLog.track(fullPath) - + fullPath = os.path.normpath(fullPath) + Path.Log.track(fullPath) return fullPath @@ -266,7 +263,7 @@ def buildPostList(job): postlist = [] if orderby == "Fixture": - PathLog.debug("Ordering by Fixture") + Path.Log.debug("Ordering by Fixture") # Order by fixture means all operations and tool changes will be # completed in one fixture before moving to the next. @@ -294,13 +291,13 @@ def buildPostList(job): if tc is not None and PathUtil.opProperty(obj, "Active"): if tc.ToolNumber != currTool: sublist.append(tc) - PathLog.debug("Appending TC: {}".format(tc.Name)) + Path.Log.debug("Appending TC: {}".format(tc.Name)) currTool = tc.ToolNumber sublist.append(obj) postlist.append((f, sublist)) elif orderby == "Tool": - PathLog.debug("Ordering by Tool") + Path.Log.debug("Ordering by Tool") # Order by tool means tool changes are minimized. # all operations with the current tool are processed in the current # fixture before moving to the next fixture. @@ -329,13 +326,13 @@ def buildPostList(job): curlist = [] # list of ops for tool, will repeat for each fixture sublist = [] # list of ops for output splitting - PathLog.track(job.PostProcessorOutputFile) + Path.Log.track(job.PostProcessorOutputFile) for idx, obj in enumerate(job.Operations.Group): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) # check if the operation is active if not getattr(obj, "Active", True): - PathLog.track() + Path.Log.track() continue # Determine the proper string for the Op's TC @@ -346,7 +343,7 @@ def buildPostList(job): tcstring = f"{tc.ToolNumber}" else: tcstring = re.sub(r"[^\w\d-]", "_", tc.Label) - PathLog.track(toolstring) + Path.Log.track(toolstring) if tc is None or tc.ToolNumber == currTool: curlist.append(obj) @@ -374,7 +371,7 @@ def buildPostList(job): postlist.append((toolstring, sublist)) elif orderby == "Operation": - PathLog.debug("Ordering by Operation") + Path.Log.debug("Ordering by Operation") # Order by operation means ops are done in each fixture in # sequence. currTool = None @@ -388,7 +385,7 @@ def buildPostList(job): continue sublist = [] - PathLog.debug("obj: {}".format(obj.Name)) + Path.Log.debug("obj: {}".format(obj.Name)) for f in wcslist: fobj = _TempObject() @@ -415,10 +412,10 @@ def buildPostList(job): postlist.append((obj.Label, sublist)) if job.SplitOutput: - PathLog.track() + Path.Log.track() return postlist else: - PathLog.track() + Path.Log.track() finalpostlist = [ ("allitems", [item for slist in postlist for item in slist[1]]) ] @@ -429,7 +426,7 @@ class DlgSelectPostProcessor: def __init__(self, parent=None): self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgSelectPostProcessor.ui") firstItem = None - for post in PathPreferences.allEnabledPostProcessors(): + for post in Path.Preferences.allEnabledPostProcessors(): item = QtGui.QListWidgetItem(post) item.setFlags( QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled @@ -467,7 +464,7 @@ class CommandPathPost: def resolvePostProcessor(self, job): if hasattr(job, "PostProcessor"): - post = PathPreferences.defaultPostProcessor() + post = Path.Preferences.defaultPostProcessor() if job.PostProcessor: post = job.PostProcessor if post and PostProcessor.exists(post): @@ -493,18 +490,18 @@ class CommandPathPost: return False def exportObjectsWith(self, objs, partname, job, sequence, extraargs=None): - PathLog.track(extraargs) + Path.Log.track(extraargs) # check if the user has a project and has set the default post and # output filename # extraargs can be passed in at this time - PathLog.track(partname, sequence) - PathLog.track(objs) + Path.Log.track(partname, sequence) + Path.Log.track(objs) # partname = objs[0] # slist = objs[1] - PathLog.track(objs, partname) + Path.Log.track(objs, partname) - postArgs = PathPreferences.defaultPostProcessorArgs() + postArgs = Path.Preferences.defaultPostProcessorArgs() if hasattr(job, "PostProcessorArgs") and job.PostProcessorArgs: postArgs = job.PostProcessorArgs elif hasattr(job, "PostProcessor") and job.PostProcessor: @@ -513,7 +510,7 @@ class CommandPathPost: if extraargs is not None: postArgs += " {}".format(extraargs) - PathLog.track(postArgs) + Path.Log.track(postArgs) postname = self.resolvePostProcessor(job) # filename = "-" @@ -530,9 +527,9 @@ class CommandPathPost: return (True, "", filename) def Activated(self): - PathLog.track() + Path.Log.track() FreeCAD.ActiveDocument.openTransaction("Post Process the Selected path(s)") - FreeCADGui.addModule("PathScripts.PathPost") + FreeCADGui.addModule("Path.Post.Command") # Attempt to figure out what the user wants to post-process # If a job is selected, post that. @@ -564,7 +561,7 @@ class CommandPathPost: if hasattr(o, "Proxy"): if isinstance(o.Proxy, PathJob.ObjectJob): targetlist.append(o.Label) - PathLog.debug("Possible post objects: {}".format(targetlist)) + Path.Log.debug("Possible post objects: {}".format(targetlist)) if len(targetlist) > 1: jobname, result = QtGui.QInputDialog.getItem( None, translate("Path", "Choose a Path Job"), None, targetlist @@ -576,7 +573,7 @@ class CommandPathPost: jobname = targetlist[0] job = FreeCAD.ActiveDocument.getObject(jobname) - PathLog.debug("about to postprocess job: {}".format(job.Name)) + Path.Log.debug("about to postprocess job: {}".format(job.Name)) postlist = buildPostList(job) # filename = resolveFileName(job, "allitems", 0) @@ -591,7 +588,7 @@ class CommandPathPost: result, gcode, name = self.exportObjectsWith(sublist, partname, job, idx) filenames.append(name) - PathLog.track(result, gcode, name) + Path.Log.track(result, gcode, name) if name is None: success = False @@ -612,13 +609,13 @@ class CommandPathPost: # gcode = self.exportObjectsWith(finalpostlist, "allitems", job, 1) # success = gcode is not None - PathLog.track(success) + Path.Log.track(success) if success: if hasattr(job, "LastPostProcessDate"): job.LastPostProcessDate = str(datetime.now()) if hasattr(job, "LastPostProcessOutput"): job.LastPostProcessOutput = " \n".join(filenames) - PathLog.track(job.LastPostProcessOutput) + Path.Log.track(job.LastPostProcessOutput) FreeCAD.ActiveDocument.commitTransaction() else: FreeCAD.ActiveDocument.abortTransaction() diff --git a/src/Mod/Path/PathScripts/PathPostProcessor.py b/src/Mod/Path/Path/Post/Processor.py similarity index 91% rename from src/Mod/Path/PathScripts/PathPostProcessor.py rename to src/Mod/Path/Path/Post/Processor.py index 85857c2394..c80bebaa46 100644 --- a/src/Mod/Path/PathScripts/PathPostProcessor.py +++ b/src/Mod/Path/Path/Post/Processor.py @@ -20,23 +20,22 @@ # * * # *************************************************************************** -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences +import Path import sys -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class PostProcessor: @classmethod def exists(cls, processor): - return processor in PathPreferences.allAvailablePostProcessors() + return processor in Path.Preferences.allAvailablePostProcessors() @classmethod def load(cls, processor): - PathLog.track(processor) + Path.Log.track(processor) syspath = sys.path - paths = PathPreferences.searchPathsPost() + paths = Path.Preferences.searchPathsPost() paths.extend(sys.path) sys.path = paths diff --git a/src/Mod/Path/PathScripts/PostUtils.py b/src/Mod/Path/Path/Post/Utils.py similarity index 96% rename from src/Mod/Path/PathScripts/PostUtils.py rename to src/Mod/Path/Path/Post/Utils.py index ec6b21c609..b4090afde3 100644 --- a/src/Mod/Path/PathScripts/PostUtils.py +++ b/src/Mod/Path/Path/Post/Utils.py @@ -34,8 +34,7 @@ import FreeCAD import Path import Part -from PathMachineState import MachineState -from PathScripts.PathGeom import CmdMoveArc, edgeForCmd, cmdsForEdge +from Path.Base.MachineState import MachineState translate = FreeCAD.Qt.translate FreeCADGui = None @@ -216,16 +215,16 @@ def splitArcs(path): machine = MachineState() for command in path.Commands: - if command.Name not in CmdMoveArc: + if command.Name not in Path.Geom.CmdMoveArc: machine.addCommand(command) results.append(command) continue - edge = edgeForCmd(command, machine.getPosition()) + edge = Path.Geom.edgeForCmd(command, machine.getPosition()) pts = edge.discretize(Deflection=deflection) edges = [Part.makeLine(v1, v2) for v1, v2 in zip(pts, pts[1:])] for edge in edges: - results.extend(cmdsForEdge(edge)) + results.extend(Path.Geom.cmdsForEdge(edge)) machine.addCommand(command) diff --git a/src/Mod/Path/PathScripts/PostUtilsArguments.py b/src/Mod/Path/Path/Post/UtilsArguments.py similarity index 100% rename from src/Mod/Path/PathScripts/PostUtilsArguments.py rename to src/Mod/Path/Path/Post/UtilsArguments.py diff --git a/src/Mod/Path/PathScripts/PostUtilsExport.py b/src/Mod/Path/Path/Post/UtilsExport.py similarity index 98% rename from src/Mod/Path/PathScripts/PostUtilsExport.py rename to src/Mod/Path/Path/Post/UtilsExport.py index 9c9263f8af..aa525aac18 100644 --- a/src/Mod/Path/PathScripts/PostUtilsExport.py +++ b/src/Mod/Path/Path/Post/UtilsExport.py @@ -31,10 +31,9 @@ import datetime import os import FreeCAD - -from PathScripts import PathToolController -from PathScripts import PostUtils -from PathScripts import PostUtilsParse +import Path.Post.Utils as PostUtils +import Path.Post.UtilsParse as PostUtilsParse +import Path.Tool.Controller as PathToolController # to distinguish python built-in open function from the one declared below diff --git a/src/Mod/Path/PathScripts/PostUtilsParse.py b/src/Mod/Path/Path/Post/UtilsParse.py similarity index 99% rename from src/Mod/Path/PathScripts/PostUtilsParse.py rename to src/Mod/Path/Path/Post/UtilsParse.py index 9c559c9d21..3fb33334c5 100644 --- a/src/Mod/Path/PathScripts/PostUtilsParse.py +++ b/src/Mod/Path/Path/Post/UtilsParse.py @@ -33,8 +33,7 @@ import FreeCAD from FreeCAD import Units import Path - -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils def create_comment(comment_string, comment_symbol): diff --git a/src/Mod/Path/Path/Post/__init__.py b/src/Mod/Path/Path/Post/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/post/KineticNCBeamicon2_post.py b/src/Mod/Path/Path/Post/scripts/KineticNCBeamicon2_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/KineticNCBeamicon2_post.py rename to src/Mod/Path/Path/Post/scripts/KineticNCBeamicon2_post.py index 1a0204d7fe..1b704aad63 100644 --- a/src/Mod/Path/PathScripts/post/KineticNCBeamicon2_post.py +++ b/src/Mod/Path/Path/Post/scripts/KineticNCBeamicon2_post.py @@ -35,10 +35,10 @@ from __future__ import print_function import FreeCAD from FreeCAD import Units import Path +import Path.Post.Utils as PostUtils import argparse import datetime import shlex -from PathScripts import PostUtils from PathScripts import PathUtils TOOLTIP = """ diff --git a/src/Mod/Path/Path/Post/scripts/__init__.py b/src/Mod/Path/Path/Post/scripts/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/PathScripts/post/centroid_post.py b/src/Mod/Path/Path/Post/scripts/centroid_post.py similarity index 98% rename from src/Mod/Path/PathScripts/post/centroid_post.py rename to src/Mod/Path/Path/Post/scripts/centroid_post.py index 6fe06202bb..b61899da5f 100644 --- a/src/Mod/Path/PathScripts/post/centroid_post.py +++ b/src/Mod/Path/Path/Post/scripts/centroid_post.py @@ -27,15 +27,15 @@ from __future__ import print_function import os import FreeCAD from FreeCAD import Units +import Path.Post.Utils as PostUtils import datetime -import PathScripts -import PathScripts.PostUtils as PostUtils +import Path TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to take a pseudo-gcode fragment outputted by a Path object, and output real GCode suitable for a centroid 3 axis mill. This postprocessor, once placed -in the appropriate PathScripts folder, can be used directly from inside +in the appropriate Path/Tool folder, can be used directly from inside FreeCAD, via the GUI importer or via python scripts with: import centroid_post @@ -188,7 +188,7 @@ def export(objectslist, filename, argstring): if OUTPUT_COMMENTS: for item in objectslist: if hasattr(item, "Proxy") and isinstance( - item.Proxy, PathScripts.PathToolController.ToolController + item.Proxy, Path.Tool.Controller.ToolController ): gcode += ";T{}={}\n".format(item.ToolNumber, item.Name) gcode += linenumber() + ";begin preamble\n" diff --git a/src/Mod/Path/PathScripts/post/comparams_post.py b/src/Mod/Path/Path/Post/scripts/comparams_post.py similarity index 98% rename from src/Mod/Path/PathScripts/post/comparams_post.py rename to src/Mod/Path/Path/Post/scripts/comparams_post.py index aa5c275e98..d4b1af4018 100644 --- a/src/Mod/Path/PathScripts/post/comparams_post.py +++ b/src/Mod/Path/Path/Post/scripts/comparams_post.py @@ -22,7 +22,7 @@ import FreeCAD import Path -import PathScripts.PostUtils as PostUtils +import Path.Post.Utils as PostUtils TOOLTIP = """Example Post, using Path.Commands instead of Path.toGCode strings for Path gcode output.""" diff --git a/src/Mod/Path/PathScripts/post/dumper_post.py b/src/Mod/Path/Path/Post/scripts/dumper_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/dumper_post.py rename to src/Mod/Path/Path/Post/scripts/dumper_post.py index a89d515d6b..753c367f42 100644 --- a/src/Mod/Path/PathScripts/post/dumper_post.py +++ b/src/Mod/Path/Path/Post/scripts/dumper_post.py @@ -30,7 +30,7 @@ doesn't do any manipulation of the path and doesn't write anything to disk. It shows the dialog so you can see it. Useful for debugging, but not much else. """ import datetime -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils now = datetime.datetime.now() SHOW_EDITOR = True diff --git a/src/Mod/Path/PathScripts/post/dxf_post.py b/src/Mod/Path/Path/Post/scripts/dxf_post.py similarity index 87% rename from src/Mod/Path/PathScripts/post/dxf_post.py rename to src/Mod/Path/Path/Post/scripts/dxf_post.py index 91901e6be1..e08d66d398 100644 --- a/src/Mod/Path/PathScripts/post/dxf_post.py +++ b/src/Mod/Path/Path/Post/scripts/dxf_post.py @@ -22,12 +22,10 @@ # ***************************************************************************/ from __future__ import print_function import FreeCAD -import datetime -import PathScripts.PathGeom as PathGeom import Part -import importDXF import Path -import PathScripts.PathLog as PathLog +import datetime +import importDXF TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to @@ -52,11 +50,11 @@ now = datetime.datetime.now() OUTPUT_HEADER = True if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) # to distinguish python built-in open function from the one declared below @@ -94,8 +92,8 @@ def dxfWrite(objlist, filename): def parse(pathobj): """accepts a Path object. Returns a list of wires""" - feedcommands = PathGeom.CmdMove - rapidcommands = PathGeom.CmdMoveRapid + feedcommands = Path.Geom.CmdMove + rapidcommands = Path.Geom.CmdMoveRapid edges = [] objlist = [] @@ -103,7 +101,7 @@ def parse(pathobj): # Gotta start somewhere. Assume 0,0,0 curPoint = FreeCAD.Vector(0, 0, 0) for c in pathobj.Path.Commands: - PathLog.debug("{} -> {}".format(curPoint, c)) + Path.Log.debug("{} -> {}".format(curPoint, c)) if "Z" in c.Parameters: newparams = c.Parameters newparams.pop("Z", None) @@ -114,7 +112,7 @@ def parse(pathobj): # ignore gcode that isn't moving if flatcommand.Name not in feedcommands + rapidcommands: - PathLog.debug("non move") + Path.Log.debug("non move") continue # ignore pure vertical feed and rapid @@ -122,13 +120,13 @@ def parse(pathobj): flatcommand.Parameters.get("X", curPoint.x) == curPoint.x and flatcommand.Parameters.get("Y", curPoint.y) == curPoint.y ): - PathLog.debug("vertical") + Path.Log.debug("vertical") continue # feeding move. Build an edge if flatcommand.Name in feedcommands: - edges.append(PathGeom.edgeForCmd(flatcommand, curPoint)) - PathLog.debug("feeding move") + edges.append(Path.Geom.edgeForCmd(flatcommand, curPoint)) + Path.Log.debug("feeding move") # update the curpoint curPoint.x = flatcommand.Parameters.get("X", curPoint.x) diff --git a/src/Mod/Path/PathScripts/post/dynapath_post.py b/src/Mod/Path/Path/Post/scripts/dynapath_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/dynapath_post.py rename to src/Mod/Path/Path/Post/scripts/dynapath_post.py index 936d1f6b97..5f1798d50a 100644 --- a/src/Mod/Path/PathScripts/post/dynapath_post.py +++ b/src/Mod/Path/Path/Post/scripts/dynapath_post.py @@ -33,10 +33,10 @@ from __future__ import print_function import FreeCAD from FreeCAD import Units +import Path.Post.Utils as PostUtils import argparse import datetime import shlex -from PathScripts import PostUtils TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to diff --git a/src/Mod/Path/PathScripts/post/example_post.py b/src/Mod/Path/Path/Post/scripts/example_post.py similarity index 100% rename from src/Mod/Path/PathScripts/post/example_post.py rename to src/Mod/Path/Path/Post/scripts/example_post.py diff --git a/src/Mod/Path/PathScripts/post/example_pre.py b/src/Mod/Path/Path/Post/scripts/example_pre.py similarity index 93% rename from src/Mod/Path/PathScripts/post/example_pre.py rename to src/Mod/Path/Path/Post/scripts/example_pre.py index 9ac769a519..8c2a0a599c 100644 --- a/src/Mod/Path/PathScripts/post/example_pre.py +++ b/src/Mod/Path/Path/Post/scripts/example_pre.py @@ -32,17 +32,16 @@ Read the Path Workbench documentation to know how to create Path objects from GCode. """ -import os -import Path import FreeCAD -import PathScripts.PathLog as PathLog +import Path +import os -# LEVEL = PathLog.Level.DEBUG -LEVEL = PathLog.Level.INFO -PathLog.setLevel(LEVEL, PathLog.thisModule()) +# LEVEL = Path.Log.Level.DEBUG +LEVEL = Path.Log.Level.INFO +Path.Log.setLevel(LEVEL, Path.Log.thisModule()) -if LEVEL == PathLog.Level.DEBUG: - PathLog.trackModule(PathLog.thisModule()) +if LEVEL == Path.Log.Level.DEBUG: + Path.Log.trackModule(Path.Log.thisModule()) # to distinguish python built-in open function from the one declared below @@ -52,7 +51,7 @@ if open.__module__ in ["__builtin__", "io"]: def open(filename): "called when freecad opens a file." - PathLog.track(filename) + Path.Log.track(filename) docname = os.path.splitext(os.path.basename(filename))[0] doc = FreeCAD.newDocument(docname) insert(filename, doc.Name) @@ -60,7 +59,7 @@ def open(filename): def insert(filename, docname): "called when freecad imports a file" - PathLog.track(filename) + Path.Log.track(filename) gfile = pythonopen(filename) gcode = gfile.read() gfile.close() @@ -74,7 +73,7 @@ def insert(filename, docname): def parse(inputstring): "parse(inputstring): returns a parsed output string" print("preprocessing...") - PathLog.track(inputstring) + Path.Log.track(inputstring) # split the input by line lines = inputstring.split("\n") output = [] diff --git a/src/Mod/Path/PathScripts/post/fablin_post.py b/src/Mod/Path/Path/Post/scripts/fablin_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/fablin_post.py rename to src/Mod/Path/Path/Post/scripts/fablin_post.py index 74b01710fc..0c106f17f1 100644 --- a/src/Mod/Path/PathScripts/post/fablin_post.py +++ b/src/Mod/Path/Path/Post/scripts/fablin_post.py @@ -25,7 +25,7 @@ # *************************************************************************** import datetime -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils now = datetime.datetime.now() diff --git a/src/Mod/Path/PathScripts/post/fanuc_post.py b/src/Mod/Path/Path/Post/scripts/fanuc_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/fanuc_post.py rename to src/Mod/Path/Path/Post/scripts/fanuc_post.py index b5829a1ed1..afb7b8244f 100644 --- a/src/Mod/Path/PathScripts/post/fanuc_post.py +++ b/src/Mod/Path/Path/Post/scripts/fanuc_post.py @@ -29,7 +29,7 @@ import argparse import datetime import shlex import os.path -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to diff --git a/src/Mod/Path/PathScripts/post/gcode_pre.py b/src/Mod/Path/Path/Post/scripts/gcode_pre.py similarity index 93% rename from src/Mod/Path/PathScripts/post/gcode_pre.py rename to src/Mod/Path/Path/Post/scripts/gcode_pre.py index 508b8aed12..8dc43ec50a 100644 --- a/src/Mod/Path/PathScripts/post/gcode_pre.py +++ b/src/Mod/Path/Path/Post/scripts/gcode_pre.py @@ -42,28 +42,28 @@ Read the Path Workbench documentation to know how to create Path objects from GCode. """ -import os import FreeCAD +import Path import PathScripts.PathUtils as PathUtils -import PathScripts.PathLog as PathLog +import os import re from PySide.QtCore import QT_TRANSLATE_NOOP if FreeCAD.GuiUp: - import PathScripts.PathCustomGui as PathCustomGui + import Path.Op.Gui.Custom as PathCustomGui PathCustom = PathCustomGui.PathCustom else: - import PathScripts.PathCustom as PathCustom + import Path.Op.Custom as PathCustom translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class PathNoActiveDocumentException(Exception): @@ -87,7 +87,7 @@ if open.__module__ in ["__builtin__", "io"]: def open(filename): """called when freecad opens a file.""" - PathLog.track(filename) + Path.Log.track(filename) docname = os.path.splitext(os.path.basename(filename))[0] doc = FreeCAD.newDocument(docname) insert(filename, doc.Name) @@ -140,7 +140,7 @@ def parse(inputstring): axis = ["X", "Y", "Z", "A", "B", "C", "U", "V", "W"] FreeCAD.Console.PrintMessage("preprocessing...\n") - PathLog.track(inputstring) + Path.Log.track(inputstring) # split the input by line lines = inputstring.splitlines() output = [] @@ -183,7 +183,7 @@ def parse(inputstring): def _identifygcodeByToolNumberList(filename): """called when freecad imports a file""" - PathLog.track(filename) + Path.Log.track(filename) gcodeByToolNumberList = [] gfile = pythonopen(filename) @@ -217,16 +217,16 @@ def _identifygcodeByToolNumberList(filename): def insert(filename, docname=None): """called when freecad imports a file""" - PathLog.track(filename) + Path.Log.track(filename) try: if not _isImportEnvironmentReady(): return except PathNoActiveDocumentException: - PathLog.error(translate("Path_Gcode_pre", "No active document")) + Path.Log.error(translate("Path_Gcode_pre", "No active document")) return except PathNoJobException: - PathLog.error(translate("Path_Gcode_pre", "No job object")) + Path.Log.error(translate("Path_Gcode_pre", "No job object")) return # Create a Custom operation for each gcode-toolNumber pair diff --git a/src/Mod/Path/PathScripts/post/grbl_post.py b/src/Mod/Path/Path/Post/scripts/grbl_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/grbl_post.py rename to src/Mod/Path/Path/Post/scripts/grbl_post.py index 4613683304..5c27cd5fcf 100755 --- a/src/Mod/Path/PathScripts/post/grbl_post.py +++ b/src/Mod/Path/Path/Post/scripts/grbl_post.py @@ -26,11 +26,12 @@ import FreeCAD from FreeCAD import Units -import PathScripts.PostUtils as PostUtils +import Path +import Path.Base.Util as PathUtil +import Path.Post.Utils as PostUtils import argparse import datetime import shlex -import PathScripts.PathUtil as PathUtil import re diff --git a/src/Mod/Path/PathScripts/post/heidenhain_post.py b/src/Mod/Path/Path/Post/scripts/heidenhain_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/heidenhain_post.py rename to src/Mod/Path/Path/Post/scripts/heidenhain_post.py index a1880a0605..418db4ea64 100644 --- a/src/Mod/Path/PathScripts/post/heidenhain_post.py +++ b/src/Mod/Path/Path/Post/scripts/heidenhain_post.py @@ -21,9 +21,10 @@ # HEDENHAIN Post-Processor for FreeCAD import argparse -import shlex +import Path.Post.Utils as PostUtils +import Path import PathScripts -from PathScripts import PostUtils +import shlex import math # **************************************************************************# @@ -186,7 +187,7 @@ TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to take a pseudo-gcode fragment outputted by a Path object, and output real GCode suitable for a heidenhain 3 axis mill. This postprocessor, once placed -in the appropriate PathScripts folder, can be used directly from inside +in the appropriate Path/Tool folder, can be used directly from inside FreeCAD, via the GUI importer or via python scripts with: import heidenhain_post @@ -343,21 +344,21 @@ def export(objectslist, filename, argstring): LBLIZE_STAUS = False # useful to get idea of object kind - if isinstance(obj.Proxy, PathScripts.PathToolController.ToolController): + if isinstance(obj.Proxy, Path.Tool.Controller.ToolController): Object_Kind = "TOOL" # like we go to change tool position MACHINE_LAST_POSITION["X"] = 99999 MACHINE_LAST_POSITION["Y"] = 99999 MACHINE_LAST_POSITION["Z"] = 99999 - elif isinstance(obj.Proxy, PathScripts.PathProfileEdges.ObjectProfile): + elif isinstance(obj.Proxy, Path.Op.ProfileEdges.ObjectProfile): Object_Kind = "PROFILE" if LBLIZE_ACTIVE: LBLIZE_STAUS = True - elif isinstance(obj.Proxy, PathScripts.PathMillFace.ObjectFace): + elif isinstance(obj.Proxy, Path.Op.MillFace.ObjectFace): Object_Kind = "FACE" if LBLIZE_ACTIVE: LBLIZE_STAUS = True - elif isinstance(obj.Proxy, PathScripts.PathHelix.ObjectHelix): + elif isinstance(obj.Proxy, Path.Op.Helix.ObjectHelix): Object_Kind = "HELIX" # If used compensated path, store, recompute and diff when asked diff --git a/src/Mod/Path/PathScripts/post/jtech_post.py b/src/Mod/Path/Path/Post/scripts/jtech_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/jtech_post.py rename to src/Mod/Path/Path/Post/scripts/jtech_post.py index f753357584..36e5b1d498 100644 --- a/src/Mod/Path/PathScripts/post/jtech_post.py +++ b/src/Mod/Path/Path/Post/scripts/jtech_post.py @@ -28,7 +28,7 @@ import Path import argparse import datetime import shlex -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to diff --git a/src/Mod/Path/PathScripts/post/linuxcnc_post.py b/src/Mod/Path/Path/Post/scripts/linuxcnc_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/linuxcnc_post.py rename to src/Mod/Path/Path/Post/scripts/linuxcnc_post.py index 2d0f9e3d6d..d21eba1bad 100644 --- a/src/Mod/Path/PathScripts/post/linuxcnc_post.py +++ b/src/Mod/Path/Path/Post/scripts/linuxcnc_post.py @@ -28,7 +28,7 @@ import Path import argparse import datetime import shlex -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to diff --git a/src/Mod/Path/PathScripts/post/mach3_mach4_post.py b/src/Mod/Path/Path/Post/scripts/mach3_mach4_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/mach3_mach4_post.py rename to src/Mod/Path/Path/Post/scripts/mach3_mach4_post.py index 9fd054fb5a..d4cb8ecb66 100644 --- a/src/Mod/Path/PathScripts/post/mach3_mach4_post.py +++ b/src/Mod/Path/Path/Post/scripts/mach3_mach4_post.py @@ -27,7 +27,7 @@ import Path import argparse import datetime import shlex -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to diff --git a/src/Mod/Path/PathScripts/post/marlin_post.py b/src/Mod/Path/Path/Post/scripts/marlin_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/marlin_post.py rename to src/Mod/Path/Path/Post/scripts/marlin_post.py index ba990168c8..a948ac9df5 100644 --- a/src/Mod/Path/PathScripts/post/marlin_post.py +++ b/src/Mod/Path/Path/Post/scripts/marlin_post.py @@ -32,8 +32,9 @@ import argparse import shlex import FreeCAD from FreeCAD import Units -import PathScripts.PathUtil as PathUtil -import PathScripts.PostUtils as PostUtils +import Path +import Path.Base.Util as PathUtil +import Path.Post.Utils as PostUtils Revised = "2020-11-03" # Revision date for this file. diff --git a/src/Mod/Path/PathScripts/post/nccad_post.py b/src/Mod/Path/Path/Post/scripts/nccad_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/nccad_post.py rename to src/Mod/Path/Path/Post/scripts/nccad_post.py index 2683870157..7661c888e1 100644 --- a/src/Mod/Path/PathScripts/post/nccad_post.py +++ b/src/Mod/Path/Path/Post/scripts/nccad_post.py @@ -22,7 +22,7 @@ # ****************************************************************************/ """Postprocessor to output real GCode for Max Computer GmbH nccad9.""" import FreeCAD -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils import datetime diff --git a/src/Mod/Path/PathScripts/post/opensbp_post.py b/src/Mod/Path/Path/Post/scripts/opensbp_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/opensbp_post.py rename to src/Mod/Path/Path/Post/scripts/opensbp_post.py index e76eeedc97..3d2e2af199 100644 --- a/src/Mod/Path/PathScripts/post/opensbp_post.py +++ b/src/Mod/Path/Path/Post/scripts/opensbp_post.py @@ -23,7 +23,7 @@ from __future__ import print_function import datetime -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils TOOLTIP = """ diff --git a/src/Mod/Path/PathScripts/post/opensbp_pre.py b/src/Mod/Path/Path/Post/scripts/opensbp_pre.py similarity index 99% rename from src/Mod/Path/PathScripts/post/opensbp_pre.py rename to src/Mod/Path/Path/Post/scripts/opensbp_pre.py index 3bd4117d69..f0815d9442 100644 --- a/src/Mod/Path/PathScripts/post/opensbp_pre.py +++ b/src/Mod/Path/Path/Post/scripts/opensbp_pre.py @@ -49,7 +49,8 @@ Many other OpenSBP commands not handled """ from __future__ import print_function import FreeCAD -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Util as PathUtil import os import Path diff --git a/src/Mod/Path/PathScripts/post/philips_post.py b/src/Mod/Path/Path/Post/scripts/philips_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/philips_post.py rename to src/Mod/Path/Path/Post/scripts/philips_post.py index 74bc2612e0..d6e57cee6d 100644 --- a/src/Mod/Path/PathScripts/post/philips_post.py +++ b/src/Mod/Path/Path/Post/scripts/philips_post.py @@ -27,7 +27,7 @@ import FreeCAD import argparse import time -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils import math TOOLTIP = """Post processor for Maho M 600E mill diff --git a/src/Mod/Path/PathScripts/post/refactored_centroid_post.py b/src/Mod/Path/Path/Post/scripts/refactored_centroid_post.py similarity index 98% rename from src/Mod/Path/PathScripts/post/refactored_centroid_post.py rename to src/Mod/Path/Path/Post/scripts/refactored_centroid_post.py index a9b57a4287..825106a123 100644 --- a/src/Mod/Path/PathScripts/post/refactored_centroid_post.py +++ b/src/Mod/Path/Path/Post/scripts/refactored_centroid_post.py @@ -26,8 +26,8 @@ from __future__ import print_function -from PathScripts import PostUtilsArguments -from PathScripts import PostUtilsExport +import Path.Post.UtilsArguments as PostUtilsArguments +import Path.Post.UtilsExport as PostUtilsExport # # The following variables need to be global variables diff --git a/src/Mod/Path/PathScripts/post/refactored_grbl_post.py b/src/Mod/Path/Path/Post/scripts/refactored_grbl_post.py similarity index 98% rename from src/Mod/Path/PathScripts/post/refactored_grbl_post.py rename to src/Mod/Path/Path/Post/scripts/refactored_grbl_post.py index 9e11a5ee76..f52952d8f4 100644 --- a/src/Mod/Path/PathScripts/post/refactored_grbl_post.py +++ b/src/Mod/Path/Path/Post/scripts/refactored_grbl_post.py @@ -27,8 +27,8 @@ from __future__ import print_function -from PathScripts import PostUtilsArguments -from PathScripts import PostUtilsExport +import Path.Post.UtilsArguments as PostUtilsArguments +import Path.Post.UtilsExport as PostUtilsExport # # The following variables need to be global variables diff --git a/src/Mod/Path/PathScripts/post/refactored_linuxcnc_post.py b/src/Mod/Path/Path/Post/scripts/refactored_linuxcnc_post.py similarity index 98% rename from src/Mod/Path/PathScripts/post/refactored_linuxcnc_post.py rename to src/Mod/Path/Path/Post/scripts/refactored_linuxcnc_post.py index b6a250d835..23b33dbc07 100644 --- a/src/Mod/Path/PathScripts/post/refactored_linuxcnc_post.py +++ b/src/Mod/Path/Path/Post/scripts/refactored_linuxcnc_post.py @@ -24,8 +24,8 @@ from __future__ import print_function -from PathScripts import PostUtilsArguments -from PathScripts import PostUtilsExport +import Path.Post.UtilsArguments as PostUtilsArguments +import Path.Post.UtilsExport as PostUtilsExport # # The following variables need to be global variables diff --git a/src/Mod/Path/PathScripts/post/refactored_mach3_mach4_post.py b/src/Mod/Path/Path/Post/scripts/refactored_mach3_mach4_post.py similarity index 98% rename from src/Mod/Path/PathScripts/post/refactored_mach3_mach4_post.py rename to src/Mod/Path/Path/Post/scripts/refactored_mach3_mach4_post.py index e0078f6a1d..d4b6c4ac17 100644 --- a/src/Mod/Path/PathScripts/post/refactored_mach3_mach4_post.py +++ b/src/Mod/Path/Path/Post/scripts/refactored_mach3_mach4_post.py @@ -23,8 +23,8 @@ # ***************************************************************************/ from __future__ import print_function -from PathScripts import PostUtilsArguments -from PathScripts import PostUtilsExport +import Path.Post.UtilsArguments as PostUtilsArguments +import Path.Post.UtilsExport as PostUtilsExport # # The following variables need to be global variables diff --git a/src/Mod/Path/PathScripts/post/refactored_test_post.py b/src/Mod/Path/Path/Post/scripts/refactored_test_post.py similarity index 98% rename from src/Mod/Path/PathScripts/post/refactored_test_post.py rename to src/Mod/Path/Path/Post/scripts/refactored_test_post.py index eb019200af..17f0d58be0 100644 --- a/src/Mod/Path/PathScripts/post/refactored_test_post.py +++ b/src/Mod/Path/Path/Post/scripts/refactored_test_post.py @@ -24,8 +24,8 @@ from __future__ import print_function -from PathScripts import PostUtilsArguments -from PathScripts import PostUtilsExport +import Path.Post.UtilsArguments as PostUtilsArguments +import Path.Post.UtilsExport as PostUtilsExport # # The following variables need to be global variables diff --git a/src/Mod/Path/PathScripts/post/rml_post.py b/src/Mod/Path/Path/Post/scripts/rml_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/rml_post.py rename to src/Mod/Path/Path/Post/scripts/rml_post.py index 62fa837737..c2e27e31f6 100644 --- a/src/Mod/Path/PathScripts/post/rml_post.py +++ b/src/Mod/Path/Path/Post/scripts/rml_post.py @@ -36,7 +36,7 @@ http://paulbourke.net/dataformats/hpgl/ import FreeCAD import Part -import PathScripts.PostUtils as PostUtils +import Path.Post.Utils as PostUtils # to distinguish python built-in open function from the one declared below if open.__module__ in ["__builtin__", "io"]: diff --git a/src/Mod/Path/PathScripts/post/rrf_post.py b/src/Mod/Path/Path/Post/scripts/rrf_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/rrf_post.py rename to src/Mod/Path/Path/Post/scripts/rrf_post.py index 176b2af0db..4d09d7b9ba 100644 --- a/src/Mod/Path/PathScripts/post/rrf_post.py +++ b/src/Mod/Path/Path/Post/scripts/rrf_post.py @@ -31,8 +31,9 @@ import argparse import shlex import FreeCAD from FreeCAD import Units -import PathScripts.PathUtil as PathUtil -import PathScripts.PostUtils as PostUtils +import Path +import Path.Base.Util as PathUtil +import Path.Post.Utils as PostUtils Revised = "2021-10-21" # Revision date for this file. diff --git a/src/Mod/Path/PathScripts/post/slic3r_pre.py b/src/Mod/Path/Path/Post/scripts/slic3r_pre.py similarity index 100% rename from src/Mod/Path/PathScripts/post/slic3r_pre.py rename to src/Mod/Path/Path/Post/scripts/slic3r_pre.py diff --git a/src/Mod/Path/PathScripts/post/smoothie_post.py b/src/Mod/Path/Path/Post/scripts/smoothie_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/smoothie_post.py rename to src/Mod/Path/Path/Post/scripts/smoothie_post.py index 85f42a1506..0429997475 100644 --- a/src/Mod/Path/PathScripts/post/smoothie_post.py +++ b/src/Mod/Path/Path/Post/scripts/smoothie_post.py @@ -25,7 +25,7 @@ from __future__ import print_function import argparse import datetime -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils import FreeCAD from FreeCAD import Units import shlex diff --git a/src/Mod/Path/PathScripts/post/uccnc_post.py b/src/Mod/Path/Path/Post/scripts/uccnc_post.py similarity index 99% rename from src/Mod/Path/PathScripts/post/uccnc_post.py rename to src/Mod/Path/Path/Post/scripts/uccnc_post.py index ca41cdc2a7..3a70425294 100644 --- a/src/Mod/Path/PathScripts/post/uccnc_post.py +++ b/src/Mod/Path/Path/Post/scripts/uccnc_post.py @@ -37,7 +37,7 @@ import argparse import datetime # import shlex -from PathScripts import PostUtils +import Path.Post.Utils as PostUtils VERSION = "0.0.4" @@ -46,7 +46,7 @@ TOOLTIP = """ Post processor for UC-CNC. This is a postprocessor file for the Path workbench. It is used to take a pseudo-gcode fragment outputted by a Path object, and output real GCode. This postprocessor, once placed in the appropriate -PathScripts folder, can be used directly from inside FreeCAD, +Path/Tool folder, can be used directly from inside FreeCAD, via the GUI importer or via python scripts with: import UCCNC_post @@ -453,7 +453,7 @@ def export(objectslist, filename, argstring): if OUTPUT_COMMENTS: gcode += append("(preamble: begin)\n") # for obj in objectslist: - # if isinstance(obj.Proxy, PathScripts.PathToolController.ToolController): + # if isinstance(obj.Proxy, Path.Tool.Controller.ToolController): # gcode += append("(T{}={})\n".format(obj.ToolNumber, item.Name)) # error: global name 'PathScripts' is not defined for line in PREAMBLE.splitlines(False): diff --git a/src/Mod/Path/PathScripts/PathPreferences.py b/src/Mod/Path/Path/Preferences.py similarity index 90% rename from src/Mod/Path/PathScripts/PathPreferences.py rename to src/Mod/Path/Path/Preferences.py index 5148b7cbbd..5b8eaafd28 100644 --- a/src/Mod/Path/PathScripts/PathPreferences.py +++ b/src/Mod/Path/Path/Preferences.py @@ -21,16 +21,15 @@ # *************************************************************************** import FreeCAD +import Path import glob import os -import PathScripts.PathLog as PathLog -from PySide.QtGui import QMessageBox if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -54,7 +53,6 @@ LastFileToolBit = "LastFileToolBit" LastFileToolLibrary = "LastFileToolLibrary" LastFileToolShape = "LastFileToolShape" -UseLegacyTools = "UseLegacyTools" UseAbsoluteToolPaths = "UseAbsoluteToolPaths" # OpenLastLibrary = "OpenLastLibrary" @@ -75,8 +73,8 @@ def preferences(): return FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") -def pathScriptsSourcePath(): - return os.path.join(FreeCAD.getHomePath(), "Mod/Path/PathScripts/") +def pathPostSourcePath(): + return os.path.join(FreeCAD.getHomePath(), "Mod/Path/Path/Post/") def pathDefaultToolsPath(sub=None): @@ -160,8 +158,8 @@ def searchPathsPost(): if p: paths.append(p) paths.append(macroFilePath()) - paths.append(os.path.join(pathScriptsSourcePath(), "post/")) - paths.append(pathScriptsSourcePath()) + paths.append(os.path.join(pathPostSourcePath(), "scripts/")) + paths.append(pathPostSourcePath()) return paths @@ -171,9 +169,6 @@ def searchPathsTool(sub): return paths -def toolsUseLegacyTools(): - return preferences().GetBool(UseLegacyTools, False) - def toolsStoreAbsolutePaths(): return preferences().GetBool(UseAbsoluteToolPaths, False) @@ -183,19 +178,8 @@ def toolsStoreAbsolutePaths(): # return preferences().GetBool(OpenLastLibrary, False) -def setToolsSettings(legacy, relative): +def setToolsSettings(relative): pref = preferences() - if legacy: - msgBox = QMessageBox() - msgBox.setIcon(QMessageBox.Warning) - msgBox.setText( - translate( - "Path", - "Legacy tools are deprecated. They will be removed after version 0.20", - ) - ) - msgBox.exec_() - pref.SetBool(UseLegacyTools, legacy) pref.SetBool(UseAbsoluteToolPaths, relative) # pref.SetBool(OpenLastLibrary, lastlibrary) @@ -208,7 +192,7 @@ def defaultJobTemplate(): def setJobDefaults(fileName, jobTemplate, geometryTolerance, curveAccuracy): - PathLog.track( + Path.Log.track( "(%s='%s', %s, %s, %s)" % (DefaultFilePath, fileName, jobTemplate, geometryTolerance, curveAccuracy) ) @@ -320,14 +304,14 @@ def lastFileToolLibrary(): if len(libFiles) >= 1: filename = libFiles[0] setLastFileToolLibrary(filename) - PathLog.track(filename) + Path.Log.track(filename) return filename else: return None def setLastFileToolLibrary(path): - PathLog.track(path) + Path.Log.track(path) if os.path.isfile(path): # keep the path and file in sync preferences().SetString(LastPathToolLibrary, os.path.split(path)[0]) return preferences().SetString(LastFileToolLibrary, path) @@ -342,14 +326,14 @@ def setLastPathToolBit(path): def lastPathToolLibrary(): - PathLog.track() + Path.Log.track() return preferences().GetString(LastPathToolLibrary, pathDefaultToolsPath("Library")) def setLastPathToolLibrary(path): - PathLog.track(path) + Path.Log.track(path) curLib = lastFileToolLibrary() - PathLog.debug("curLib: {}".format(curLib)) + Path.Log.debug("curLib: {}".format(curLib)) if curLib and os.path.split(curLib)[0] != path: setLastFileToolLibrary("") # a path is known but not specific file return preferences().SetString(LastPathToolLibrary, path) diff --git a/src/Mod/Path/PathScripts/PathToolBit.py b/src/Mod/Path/Path/Tool/Bit.py similarity index 91% rename from src/Mod/Path/PathScripts/PathToolBit.py rename to src/Mod/Path/Path/Tool/Bit.py index 8067d9f9ca..e562517a35 100644 --- a/src/Mod/Path/PathScripts/PathToolBit.py +++ b/src/Mod/Path/Path/Tool/Bit.py @@ -21,10 +21,9 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathPropertyBag as PathPropertyBag -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Util as PathUtil +import Path.Base.PropertyBag as PathPropertyBag import json import os import zipfile @@ -46,14 +45,14 @@ _DebugFindTool = False if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) def _findToolFile(name, containerFile, typ): - PathLog.track(name) + Path.Log.track(name) if os.path.exists(name): # absolute reference return name @@ -62,10 +61,10 @@ def _findToolFile(name, containerFile, typ): paths = [os.path.join(rootPath, typ)] else: paths = [] - paths.extend(PathPreferences.searchPathsTool(typ)) + paths.extend(Path.Preferences.searchPathsTool(typ)) def _findFile(path, name): - PathLog.track(path, name) + Path.Log.track(path, name) fullPath = os.path.join(path, name) if os.path.exists(fullPath): return (True, fullPath) @@ -85,13 +84,13 @@ def _findToolFile(name, containerFile, typ): def findToolShape(name, path=None): """findToolShape(name, path) ... search for name, if relative path look in path""" - PathLog.track(name, path) + Path.Log.track(name, path) return _findToolFile(name, path, "Shape") def findToolBit(name, path=None): """findToolBit(name, path) ... search for name, if relative path look in path""" - PathLog.track(name, path) + Path.Log.track(name, path) if name.endswith(".fctb"): return _findToolFile(name, path, "Bit") return _findToolFile("{}.fctb".format(name), path, "Bit") @@ -100,16 +99,16 @@ def findToolBit(name, path=None): # Only used in ToolBit unit test module: TestPathToolBit.py def findToolLibrary(name, path=None): """findToolLibrary(name, path) ... search for name, if relative path look in path""" - PathLog.track(name, path) + Path.Log.track(name, path) if name.endswith(".fctl"): return _findToolFile(name, path, "Library") return _findToolFile("{}.fctl".format(name), path, "Library") def _findRelativePath(path, typ): - PathLog.track(path, typ) + Path.Log.track(path, typ) relative = path - for p in PathPreferences.searchPathsTool(typ): + for p in Path.Preferences.searchPathsTool(typ): if path.startswith(p): p = path[len(p) :] if os.path.sep == p[0]: @@ -136,7 +135,7 @@ def findRelativePathLibrary(path): class ToolBit(object): def __init__(self, obj, shapeFile, path=None): - PathLog.track(obj.Label, shapeFile, path) + Path.Log.track(obj.Label, shapeFile, path) self.obj = obj obj.addProperty( "App::PropertyFile", @@ -238,12 +237,12 @@ class ToolBit(object): obj.setEditorMode(prop, 0) def onChanged(self, obj, prop): - PathLog.track(obj.Label, prop) + Path.Log.track(obj.Label, prop) if prop == "BitShape" and "Restore" not in obj.State: self._setupBitShape(obj) def onDelete(self, obj, arg2=None): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) self.unloadBitBody(obj) obj.Document.removeObject(obj.Name) @@ -276,7 +275,7 @@ class ToolBit(object): obj.Shape = Part.Shape() def _loadBitBody(self, obj, path=None): - PathLog.track(obj.Label, path) + Path.Log.track(obj.Label, path) p = path if path else obj.BitShape docOpened = False doc = None @@ -291,12 +290,12 @@ class ToolBit(object): if not path and p != obj.BitShape: obj.BitShape = p - PathLog.debug("ToolBit {} using shape file: {}".format(obj.Label, p)) + Path.Log.debug("ToolBit {} using shape file: {}".format(obj.Label, p)) doc = FreeCAD.openDocument(p, True) obj.ShapeName = doc.Name docOpened = True else: - PathLog.debug("ToolBit {} already open: {}".format(obj.Label, doc)) + Path.Log.debug("ToolBit {} already open: {}".format(obj.Label, doc)) return (doc, docOpened) def _removeBitBody(self, obj): @@ -306,7 +305,7 @@ class ToolBit(object): obj.BitBody = None def _deleteBitSetup(self, obj): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) self._removeBitBody(obj) self._copyBitShape(obj) for prop in obj.BitPropertyNames: @@ -342,7 +341,7 @@ class ToolBit(object): PathUtil.setProperty(obj, prop, val) def _setupBitShape(self, obj, path=None): - PathLog.track(obj.Label) + Path.Log.track(obj.Label) activeDoc = FreeCAD.ActiveDocument (doc, docOpened) = self._loadBitBody(obj, path) @@ -359,7 +358,7 @@ class ToolBit(object): if bitBody.ViewObject: bitBody.ViewObject.Visibility = False - PathLog.debug( + Path.Log.debug( "bitBody.{} ({}): {}".format(bitBody.Label, bitBody.Name, type(bitBody)) ) @@ -367,12 +366,12 @@ class ToolBit(object): for attributes in [ o for o in bitBody.Group if PathPropertyBag.IsPropertyBag(o) ]: - PathLog.debug("Process properties from {}".format(attributes.Label)) + Path.Log.debug("Process properties from {}".format(attributes.Label)) for prop in attributes.Proxy.getCustomProperties(): self._setupProperty(obj, prop, attributes) propNames.append(prop) if not propNames: - PathLog.error( + Path.Log.error( "Did not find a PropertyBag in {} - not a ToolBit shape?".format( docName ) @@ -430,7 +429,7 @@ class ToolBit(object): return None def saveToFile(self, obj, path, setFile=True): - PathLog.track(path) + Path.Log.track(path) try: with open(path, "w") as fp: json.dump(self.templateAttrs(obj), fp, indent=" ") @@ -438,16 +437,16 @@ class ToolBit(object): obj.File = path return True except (OSError, IOError) as e: - PathLog.error( + Path.Log.error( "Could not save tool {} to {} ({})".format(obj.Label, path, e) ) raise def templateAttrs(self, obj): attrs = {} - attrs["version"] = 2 # Path.Tool is version 1 + attrs["version"] = 2 attrs["name"] = obj.Label - if PathPreferences.toolsStoreAbsolutePaths(): + if Path.Preferences.toolsStoreAbsolutePaths(): attrs["shape"] = obj.BitShape else: # attrs['shape'] = findRelativePathShape(obj.BitShape) @@ -466,14 +465,14 @@ class ToolBit(object): def Declaration(path): - PathLog.track(path) + Path.Log.track(path) with open(path, "r") as fp: return json.load(fp) class ToolBitFactory(object): def CreateFromAttrs(self, attrs, name="ToolBit", path=None): - PathLog.track(attrs, path) + Path.Log.track(attrs, path) obj = Factory.Create(name, attrs["shape"], path) obj.Label = attrs["name"] params = attrs["parameter"] @@ -484,7 +483,7 @@ class ToolBitFactory(object): return obj def CreateFrom(self, path, name="ToolBit"): - PathLog.track(name, path) + Path.Log.track(name, path) if not os.path.isfile(path): raise FileNotFoundError(f"{path} not found") @@ -493,11 +492,11 @@ class ToolBitFactory(object): bit = Factory.CreateFromAttrs(data, name, path) return bit except (OSError, IOError) as e: - PathLog.error("%s not a valid tool file (%s)" % (path, e)) + Path.Log.error("%s not a valid tool file (%s)" % (path, e)) raise def Create(self, name="ToolBit", shapeFile=None, path=None): - PathLog.track(name, shapeFile, path) + Path.Log.track(name, shapeFile, path) obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name) obj.Proxy = ToolBit(obj, shapeFile, path) return obj diff --git a/src/Mod/Path/PathScripts/PathToolController.py b/src/Mod/Path/Path/Tool/Controller.py similarity index 70% rename from src/Mod/Path/PathScripts/PathToolController.py rename to src/Mod/Path/Path/Tool/Controller.py index 4e29a098af..794f0ea5ab 100644 --- a/src/Mod/Path/PathScripts/PathToolController.py +++ b/src/Mod/Path/Path/Tool/Controller.py @@ -25,18 +25,15 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import Path -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathToolBit as PathToolBit -from Generators import toolchange_generator as toolchange_generator -from Generators.toolchange_generator import SpindleDirection +import Path.Tool.Bit as PathToolBit +import Path.Base.Generator.toolchange as toolchange if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -61,8 +58,8 @@ class ToolControllerTemplate: class ToolController: - def __init__(self, obj, legacyTool=False, createTool=True): - PathLog.track("tool: {}".format(legacyTool)) + def __init__(self, obj, createTool=True): + Path.Log.track("tool: ") obj.addProperty( "App::PropertyIntegerConstraint", @@ -115,7 +112,7 @@ class ToolController: setattr(obj, n[0], n[1]) if createTool: - self.ensureUseLegacyTool(obj, legacyTool) + self.ensureToolBit(obj) @classmethod def propertyEnumerations(self, dataType="data"): @@ -143,11 +140,11 @@ class ToolController: data = list() idx = 0 if dataType == "translated" else 1 - PathLog.debug(enums) + Path.Log.debug(enums) for k, v in enumerate(enums): data.append((v, [tup[idx] for tup in enums[v]])) - PathLog.debug(data) + Path.Log.debug(data) return data @@ -155,17 +152,16 @@ class ToolController: obj.setEditorMode("Placement", 2) def onDelete(self, obj, arg2=None): - if not self.usesLegacyTool(obj): - if hasattr(obj.Tool, "InList") and len(obj.Tool.InList) == 1: - if hasattr(obj.Tool.Proxy, "onDelete"): - obj.Tool.Proxy.onDelete(obj.Tool) + if hasattr(obj.Tool, "InList") and len(obj.Tool.InList) == 1: + if hasattr(obj.Tool.Proxy, "onDelete"): + obj.Tool.Proxy.onDelete(obj.Tool) def setFromTemplate(self, obj, template): """ setFromTemplate(obj, xmlItem) ... extract properties from xmlItem and assign to receiver. """ - PathLog.track(obj.Name, template) + Path.Log.track(obj.Name, template) version = 0 if template.get(ToolControllerTemplate.Version): version = int(template.get(ToolControllerTemplate.Version)) @@ -191,25 +187,26 @@ class ToolController: template.get(ToolControllerTemplate.ToolNumber) ) if template.get(ToolControllerTemplate.Tool): + self.ensureToolBit(obj) toolVersion = template.get(ToolControllerTemplate.Tool).get( ToolControllerTemplate.Version ) - if toolVersion == 1: - self.ensureUseLegacyTool(obj, True) - obj.Tool.setFromTemplate( - template.get(ToolControllerTemplate.Tool) - ) - else: - self.ensureUseLegacyTool(obj, False) + if toolVersion == 2: obj.Tool = PathToolBit.Factory.CreateFromAttrs( template.get(ToolControllerTemplate.Tool) ) - if ( - obj.Tool - and obj.Tool.ViewObject - and obj.Tool.ViewObject.Visibility - ): - obj.Tool.ViewObject.Visibility = False + else: + obj.Tool = None + if toolVersion == 1: + Path.Log.error(f"{obj.Name} - legacy Tools no longer supported - ignoring") + else: + Path.Log.error(f"{obj.Name} - unknown Tool version {toolVersion} - ignoring") + if ( + obj.Tool + and obj.Tool.ViewObject + and obj.Tool.ViewObject.Visibility + ): + obj.Tool.ViewObject.Visibility = False if template.get(ToolControllerTemplate.Expressions): for exprDef in template.get(ToolControllerTemplate.Expressions): if exprDef[ToolControllerTemplate.ExprExpr]: @@ -218,13 +215,13 @@ class ToolController: exprDef[ToolControllerTemplate.ExprExpr], ) else: - PathLog.error( + Path.Log.error( "Unsupported PathToolController template version {}".format( template.get(ToolControllerTemplate.Version) ) ) else: - PathLog.error( + Path.Log.error( "PathToolController template has no version - corrupted template file?" ) @@ -241,13 +238,10 @@ class ToolController: attrs[ToolControllerTemplate.HorizRapid] = "%s" % (obj.HorizRapid) attrs[ToolControllerTemplate.SpindleSpeed] = obj.SpindleSpeed attrs[ToolControllerTemplate.SpindleDir] = obj.SpindleDir - if self.usesLegacyTool(obj): - attrs[ToolControllerTemplate.Tool] = obj.Tool.templateAttrs() - else: - attrs[ToolControllerTemplate.Tool] = obj.Tool.Proxy.templateAttrs(obj.Tool) + attrs[ToolControllerTemplate.Tool] = obj.Tool.Proxy.templateAttrs(obj.Tool) expressions = [] for expr in obj.ExpressionEngine: - PathLog.debug("%s: %s" % (expr[0], expr[1])) + Path.Log.debug("%s: %s" % (expr[0], expr[1])) expressions.append( { ToolControllerTemplate.ExprProp: expr[0], @@ -259,33 +253,33 @@ class ToolController: return attrs def execute(self, obj): - PathLog.track() + Path.Log.track(obj.Name) args = { "toolnumber": obj.ToolNumber, "toollabel": obj.Label, "spindlespeed": obj.SpindleSpeed, - "spindledirection": SpindleDirection.OFF, + "spindledirection": toolchange.SpindleDirection.OFF, } if hasattr(obj.Tool, "SpindlePower"): if not obj.Tool.SpindlePower: - args["spindledirection"] = SpindleDirection.OFF + args["spindledirection"] = toolchange.SpindleDirection.OFF else: if obj.SpindleDir == "Forward": - args["spindledirection"] = SpindleDirection.CW + args["spindledirection"] = toolchange.SpindleDirection.CW else: - args["spindledirection"] = SpindleDirection.CCW + args["spindledirection"] = toolchange.SpindleDirection.CCW elif obj.SpindleDir == "None": - args["spindledirection"] = SpindleDirection.OFF + args["spindledirection"] = toolchange.SpindleDirection.OFF else: if obj.SpindleDir == "Forward": - args["spindledirection"] = SpindleDirection.CW + args["spindledirection"] = toolchange.SpindleDirection.CW else: - args["spindledirection"] = SpindleDirection.CCW + args["spindledirection"] = toolchange.SpindleDirection.CCW - commands = toolchange_generator.generate(**args) + commands = toolchange.generate(**args) path = Path.Path(commands) obj.Path = path @@ -294,41 +288,19 @@ class ToolController: def getTool(self, obj): """returns the tool associated with this tool controller""" - PathLog.track() + Path.Log.track() return obj.Tool - def usesLegacyTool(self, obj): - """returns True if the tool being controlled is a legacy tool""" - return isinstance(obj.Tool, Path.Tool) - - def ensureUseLegacyTool(self, obj, legacy): - if not hasattr(obj, "Tool") or (legacy != self.usesLegacyTool(obj)): - if legacy and hasattr(obj, "Tool") and len(obj.Tool.InList) == 1: - if hasattr(obj.Tool.Proxy, "onDelete"): - obj.Tool.Proxy.onDelete(obj.Tool) - obj.Document.removeObject(obj.Tool.Name) - - if hasattr(obj, "Tool"): - obj.removeProperty("Tool") - - if legacy: - obj.addProperty( - "Path::PropertyTool", - "Tool", - "Base", - QT_TRANSLATE_NOOP( - "App::Property", "The tool used by this controller" - ), - ) - else: - obj.addProperty( - "App::PropertyLink", - "Tool", - "Base", - QT_TRANSLATE_NOOP( - "App::Property", "The tool used by this controller" - ), - ) + def ensureToolBit(self, obj): + if not hasattr(obj, "Tool"): + obj.addProperty( + "App::PropertyLink", + "Tool", + "Base", + QT_TRANSLATE_NOOP( + "App::Property", "The tool used by this controller" + ), + ) def Create( @@ -338,34 +310,21 @@ def Create( assignViewProvider=True, assignTool=True, ): - legacyTool = ( - PathPreferences.toolsUseLegacyTools() - if tool is None - else isinstance(tool, Path.Tool) - ) - PathLog.track(tool, toolNumber, legacyTool) + Path.Log.track(name, tool, toolNumber, assignViewProvider, assignTool) obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) obj.Label = name - obj.Proxy = ToolController(obj, legacyTool, assignTool) + obj.Proxy = ToolController(obj, assignTool) if FreeCAD.GuiUp and assignViewProvider: ViewProvider(obj.ViewObject) if assignTool: if not tool: - if legacyTool: - tool = Path.Tool() - tool.Diameter = 5.0 - tool.Name = "Default Tool" - tool.CuttingEdgeHeight = 15.0 - tool.ToolType = "EndMill" - tool.Material = "HighSpeedSteel" - else: - tool = PathToolBit.Factory.Create() - if tool.ViewObject: - tool.ViewObject.Visibility = False + tool = PathToolBit.Factory.Create() + if tool.ViewObject: + tool.ViewObject.Visibility = False obj.Tool = tool if hasattr(obj.Tool, "SpindleDirection"): @@ -376,17 +335,19 @@ def Create( def FromTemplate(template, assignViewProvider=True): - PathLog.track() + Path.Log.track() name = template.get(ToolControllerTemplate.Name, ToolControllerTemplate.Label) obj = Create(name, assignViewProvider=True, assignTool=False) obj.Proxy.setFromTemplate(obj, template) - - return obj + if obj.Tool: + return obj + FreeCAD.ActiveDocument.removeObject(obj.Name) + return None if FreeCAD.GuiUp: # need ViewProvider class in this file to support loading of old files - from PathScripts.PathToolControllerGui import ViewProvider + from Path.Tool.Gui.Controller import ViewProvider -FreeCAD.Console.PrintLog("Loading PathToolController... done\n") +FreeCAD.Console.PrintLog("Loading Path.Tool.Gui.Controller... done\n") diff --git a/src/Mod/Path/PathScripts/PathToolBitGui.py b/src/Mod/Path/Path/Tool/Gui/Bit.py similarity index 86% rename from src/Mod/Path/PathScripts/PathToolBitGui.py rename to src/Mod/Path/Path/Tool/Gui/Bit.py index c5efb283b9..53195f4cf1 100644 --- a/src/Mod/Path/PathScripts/PathToolBitGui.py +++ b/src/Mod/Path/Path/Tool/Gui/Bit.py @@ -24,11 +24,10 @@ from PySide import QtCore, QtGui from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import FreeCADGui -import PathScripts.PathIconViewProvider as PathIconViewProvider -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathToolBit as PathToolBit -import PathScripts.PathToolBitEdit as PathToolBitEdit +import Path +import Path.Base.Gui.IconViewProvider as PathIconViewProvider +import Path.Tool.Bit as PathToolBit +import Path.Tool.Gui.BitEdit as PathToolBitEdit import os __title__ = "Tool Bit UI" @@ -38,10 +37,10 @@ __doc__ = "Task panel editor for a ToolBit" if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -51,7 +50,7 @@ class ViewProvider(object): It's sole job is to provide an icon and invoke the TaskPanel on edit.""" def __init__(self, vobj, name): - PathLog.track(name, vobj.Object) + Path.Log.track(name, vobj.Object) self.panel = None self.icon = name self.obj = vobj.Object @@ -59,7 +58,7 @@ class ViewProvider(object): vobj.Proxy = self def attach(self, vobj): - PathLog.track(vobj.Object) + Path.Log.track(vobj.Object) self.vobj = vobj self.obj = vobj.Object @@ -78,21 +77,21 @@ class ViewProvider(object): return None def onDelete(self, vobj, arg2=None): - PathLog.track(vobj.Object.Label) + Path.Log.track(vobj.Object.Label) vobj.Object.Proxy.onDelete(vobj.Object) def getDisplayMode(self, mode): return "Default" def _openTaskPanel(self, vobj, deleteOnReject): - PathLog.track() + Path.Log.track() self.panel = TaskPanel(vobj, deleteOnReject) FreeCADGui.Control.closeDialog() FreeCADGui.Control.showDialog(self.panel) self.panel.setupUi() def setCreate(self, vobj): - PathLog.track() + Path.Log.track() self._openTaskPanel(vobj, True) def setEdit(self, vobj, mode=0): @@ -125,7 +124,7 @@ class TaskPanel: """TaskPanel for the SetupSheet - if it is being edited directly.""" def __init__(self, vobj, deleteOnReject): - PathLog.track(vobj.Object.Label) + Path.Log.track(vobj.Object.Label) self.vobj = vobj self.obj = vobj.Object self.editor = PathToolBitEdit.ToolBitEditor(self.obj) @@ -153,7 +152,7 @@ class TaskPanel: FreeCAD.ActiveDocument.recompute() def updateUI(self): - PathLog.track() + Path.Log.track() self.editor.updateUI() def updateModel(self): @@ -169,7 +168,7 @@ class ToolBitGuiFactory(PathToolBit.ToolBitFactory): """Create(name = 'ToolBit') ... creates a new tool bit. It is assumed the tool will be edited immediately so the internal bit body is still attached.""" - PathLog.track(name, shapeFile, path) + Path.Log.track(name, shapeFile, path) FreeCAD.ActiveDocument.openTransaction("Create ToolBit") tool = PathToolBit.ToolBitFactory.Create(self, name, shapeFile, path) PathIconViewProvider.Attach(tool.ViewObject, name) @@ -191,7 +190,7 @@ def GetNewToolFile(parent=None): parent = QtGui.QApplication.activeWindow() foo = QtGui.QFileDialog.getSaveFileName( - parent, "Tool", PathPreferences.lastPathToolBit(), "*.fctb" + parent, "Tool", Path.Preferences.lastPathToolBit(), "*.fctb" ) if foo and foo[0]: if not isValidFileName(foo[0]): @@ -200,7 +199,7 @@ def GetNewToolFile(parent=None): msgBox.setText(msg) msgBox.exec_() else: - PathPreferences.setLastPathToolBit(os.path.dirname(foo[0])) + Path.Preferences.setLastPathToolBit(os.path.dirname(foo[0])) return foo[0] return None @@ -209,10 +208,10 @@ def GetToolFile(parent=None): if parent is None: parent = QtGui.QApplication.activeWindow() foo = QtGui.QFileDialog.getOpenFileName( - parent, "Tool", PathPreferences.lastPathToolBit(), "*.fctb" + parent, "Tool", Path.Preferences.lastPathToolBit(), "*.fctb" ) if foo and foo[0]: - PathPreferences.setLastPathToolBit(os.path.dirname(foo[0])) + Path.Preferences.setLastPathToolBit(os.path.dirname(foo[0])) return foo[0] return None @@ -221,10 +220,10 @@ def GetToolFiles(parent=None): if parent is None: parent = QtGui.QApplication.activeWindow() foo = QtGui.QFileDialog.getOpenFileNames( - parent, "Tool", PathPreferences.lastPathToolBit(), "*.fctb" + parent, "Tool", Path.Preferences.lastPathToolBit(), "*.fctb" ) if foo and foo[0]: - PathPreferences.setLastPathToolBit(os.path.dirname(foo[0][0])) + Path.Preferences.setLastPathToolBit(os.path.dirname(foo[0][0])) return foo[0] return [] @@ -233,11 +232,11 @@ def GetToolShapeFile(parent=None): if parent is None: parent = QtGui.QApplication.activeWindow() - location = PathPreferences.lastPathToolShape() + location = Path.Preferences.lastPathToolShape() if os.path.isfile(location): location = os.path.split(location)[0] elif not os.path.isdir(location): - location = PathPreferences.filePath() + location = Path.Preferences.filePath() fname = QtGui.QFileDialog.getOpenFileName( parent, "Select Tool Shape", location, "*.fcstd" @@ -245,7 +244,7 @@ def GetToolShapeFile(parent=None): if fname and fname[0]: if fname != location: newloc = os.path.dirname(fname[0]) - PathPreferences.setLastPathToolShape(newloc) + Path.Preferences.setLastPathToolShape(newloc) return fname[0] else: return None diff --git a/src/Mod/Path/PathScripts/PathToolBitCmd.py b/src/Mod/Path/Path/Tool/Gui/BitCmd.py similarity index 89% rename from src/Mod/Path/PathScripts/PathToolBitCmd.py rename to src/Mod/Path/Path/Tool/Gui/BitCmd.py index 8a388b3552..007717868e 100644 --- a/src/Mod/Path/PathScripts/PathToolBitCmd.py +++ b/src/Mod/Path/Path/Tool/Gui/BitCmd.py @@ -20,19 +20,19 @@ # * * # *************************************************************************** -from PySide import QtCore -from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import FreeCADGui -import PathScripts -import PathScripts.PathLog as PathLog +import Path +import Path.Tool import os +from PySide import QtCore +from PySide.QtCore import QT_TRANSLATE_NOOP if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class CommandToolBitCreate: @@ -56,7 +56,7 @@ class CommandToolBitCreate: return FreeCAD.ActiveDocument is not None def Activated(self): - obj = PathScripts.PathToolBit.Factory.Create() + obj = Path.Tool.Bit.Factory.Create() obj.ViewObject.Proxy.setCreate(obj.ViewObject) @@ -84,7 +84,7 @@ class CommandToolBitSave: def selectedTool(self): sel = FreeCADGui.Selection.getSelectionEx() if 1 == len(sel) and isinstance( - sel[0].Object.Proxy, PathScripts.PathToolBit.ToolBit + sel[0].Object.Proxy, Path.Tool.Bit.ToolBit ): return sel[0].Object return None @@ -108,7 +108,7 @@ class CommandToolBitSave: fname = tool.File else: fname = os.path.join( - PathScripts.PathPreferences.lastPathToolBit(), + Path.Preferences.lastPathToolBit(), tool.Label + ".fctb", ) foo = QtGui.QFileDialog.getSaveFileName( @@ -123,7 +123,7 @@ class CommandToolBitSave: if not path.endswith(".fctb"): path += ".fctb" tool.Proxy.saveToFile(tool, path) - PathScripts.PathPreferences.setLastPathToolBit(os.path.dirname(path)) + Path.Preferences.setLastPathToolBit(os.path.dirname(path)) class CommandToolBitLoad: @@ -146,7 +146,7 @@ class CommandToolBitLoad: def selectedTool(self): sel = FreeCADGui.Selection.getSelectionEx() if 1 == len(sel) and isinstance( - sel[0].Object.Proxy, PathScripts.PathToolBit.ToolBit + sel[0].Object.Proxy, Path.Tool.Bit.ToolBit ): return sel[0].Object return None @@ -155,7 +155,7 @@ class CommandToolBitLoad: return FreeCAD.ActiveDocument is not None def Activated(self): - if PathScripts.PathToolBitGui.LoadTools(): + if Path.Tool.Bit.Gui.LoadTools(): FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Path/PathScripts/PathToolBitEdit.py b/src/Mod/Path/Path/Tool/Gui/BitEdit.py similarity index 89% rename from src/Mod/Path/PathScripts/PathToolBitEdit.py rename to src/Mod/Path/Path/Tool/Gui/BitEdit.py index 9746f0e3bb..cc7657fb09 100644 --- a/src/Mod/Path/PathScripts/PathToolBitEdit.py +++ b/src/Mod/Path/Path/Tool/Gui/BitEdit.py @@ -22,20 +22,19 @@ from PySide import QtCore, QtGui import FreeCADGui -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathPropertyEditor as PathPropertyEditor -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Gui.PropertyEditor as PathPropertyEditor +import Path.Base.Gui.Util as PathGuiUtil +import Path.Base.Util as PathUtil import os import re if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class _Delegate(QtGui.QStyledItemDelegate): @@ -76,7 +75,7 @@ class ToolBitEditor(object): """ def __init__(self, tool, parentWidget=None, loadBitBody=True): - PathLog.track() + Path.Log.track() self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolBitEditor.ui") if parentWidget: @@ -102,7 +101,7 @@ class ToolBitEditor(object): self.setupAttributes(self.tool) def setupTool(self, tool): - PathLog.track() + Path.Log.track() # Can't delete and add fields to the form because of dangling references in case of # a focus change. see https://forum.freecadweb.org/viewtopic.php?f=10&t=52246#p458583 # Instead we keep widgets once created and use them for new properties, and hide all @@ -120,7 +119,7 @@ class ToolBitEditor(object): usedRows = 0 for nr, name in enumerate(tool.Proxy.toolShapeProperties(tool)): if nr < len(self.widgets): - PathLog.debug("re-use row: {} [{}]".format(nr, name)) + Path.Log.debug("re-use row: {} [{}]".format(nr, name)) label, qsb, editor = self.widgets[nr] label.setText(labelText(name)) editor.attachTo(tool, name) @@ -128,10 +127,10 @@ class ToolBitEditor(object): qsb.show() else: qsb = ui.createWidget("Gui::QuantitySpinBox") - editor = PathGui.QuantitySpinBox(qsb, tool, name) + editor = PathGuiUtil.QuantitySpinBox(qsb, tool, name) label = QtGui.QLabel(labelText(name)) self.widgets.append((label, qsb, editor)) - PathLog.debug("create row: {} [{}] {}".format(nr, name, type(qsb))) + Path.Log.debug("create row: {} [{}] {}".format(nr, name, type(qsb))) if hasattr(qsb, "editingFinished"): qsb.editingFinished.connect(self.updateTool) @@ -140,13 +139,13 @@ class ToolBitEditor(object): usedRows = usedRows + 1 # hide all rows which aren't being used - PathLog.track(usedRows, len(self.widgets)) + Path.Log.track(usedRows, len(self.widgets)) for i in range(usedRows, len(self.widgets)): label, qsb, editor = self.widgets[i] label.hide() qsb.hide() editor.attachTo(None) - PathLog.debug(" hide row: {}".format(i)) + Path.Log.debug(" hide row: {}".format(i)) img = tool.Proxy.getBitThumbnail(tool) if img: @@ -155,7 +154,7 @@ class ToolBitEditor(object): self.form.image.setPixmap(QtGui.QPixmap()) def setupAttributes(self, tool): - PathLog.track() + Path.Log.track() setup = True if not hasattr(self, "delegate"): @@ -195,16 +194,16 @@ class ToolBitEditor(object): # self.form.attrTree.collapseAll() def accept(self): - PathLog.track() + Path.Log.track() self.refresh() self.tool.Proxy.unloadBitBody(self.tool) def reject(self): - PathLog.track() + Path.Log.track() self.tool.Proxy.unloadBitBody(self.tool) def updateUI(self): - PathLog.track() + Path.Log.track() self.form.toolName.setText(self.tool.Label) self.form.shapePath.setText(self.tool.BitShape) @@ -230,7 +229,7 @@ class ToolBitEditor(object): return False def updateShape(self): - PathLog.track() + Path.Log.track() shapePath = str(self.form.shapePath.text()) # Only need to go through this exercise if the shape actually changed. if self._updateBitShape(shapePath): @@ -238,7 +237,7 @@ class ToolBitEditor(object): editor.updateSpinBox() def updateTool(self): - PathLog.track() + Path.Log.track() label = str(self.form.toolName.text()) shape = str(self.form.shapePath.text()) @@ -252,27 +251,27 @@ class ToolBitEditor(object): self.tool.Proxy._updateBitShape(self.tool) def refresh(self): - PathLog.track() + Path.Log.track() self.form.blockSignals(True) self.updateTool() self.updateUI() self.form.blockSignals(False) def selectShape(self): - PathLog.track() + Path.Log.track() path = self.tool.BitShape if not path: - path = PathPreferences.lastPathToolShape() + path = Path.Preferences.lastPathToolShape() foo = QtGui.QFileDialog.getOpenFileName( self.form, "Path - Tool Shape", path, "*.fcstd" ) if foo and foo[0]: - PathPreferences.setLastPathToolShape(os.path.dirname(foo[0])) + Path.Preferences.setLastPathToolShape(os.path.dirname(foo[0])) self.form.shapePath.setText(foo[0]) self.updateShape() def setupUI(self): - PathLog.track() + Path.Log.track() self.updateUI() self.form.toolName.editingFinished.connect(self.refresh) diff --git a/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py b/src/Mod/Path/Path/Tool/Gui/BitLibrary.py similarity index 91% rename from src/Mod/Path/PathScripts/PathToolBitLibraryGui.py rename to src/Mod/Path/Path/Tool/Gui/BitLibrary.py index a4db74a907..85b791eeca 100644 --- a/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py +++ b/src/Mod/Path/Path/Tool/Gui/BitLibrary.py @@ -24,13 +24,12 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathToolBit as PathToolBit -import PathScripts.PathToolBitEdit as PathToolBitEdit -import PathScripts.PathToolBitGui as PathToolBitGui -import PathScripts.PathToolControllerGui as PathToolControllerGui +import Path +import Path.Tool.Bit as PathToolBit +import Path.Tool.Gui.Bit as PathToolBitGui +import Path.Tool.Gui.BitEdit as PathToolBitEdit +import Path.Tool.Gui.Controller as PathToolControllerGui +import PathGui import PathScripts.PathUtilsGui as PathUtilsGui import PySide import glob @@ -43,10 +42,10 @@ from functools import partial if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) _UuidRole = PySide.QtCore.Qt.UserRole + 1 @@ -59,12 +58,12 @@ translate = FreeCAD.Qt.translate def checkWorkingDir(): # users shouldn't use the example toolbits and libraries. # working directory should be writable - PathLog.track() + Path.Log.track() - workingdir = os.path.dirname(PathPreferences.lastPathToolLibrary()) - defaultdir = os.path.dirname(PathPreferences.pathDefaultToolsPath()) + workingdir = os.path.dirname(Path.Preferences.lastPathToolLibrary()) + defaultdir = os.path.dirname(Path.Preferences.pathDefaultToolsPath()) - PathLog.debug("workingdir: {} defaultdir: {}".format(workingdir, defaultdir)) + Path.Log.debug("workingdir: {} defaultdir: {}".format(workingdir, defaultdir)) dirOK = lambda: workingdir != defaultdir and (os.access(workingdir, os.W_OK)) @@ -85,19 +84,19 @@ def checkWorkingDir(): msg = translate("Path_ToolBit", "Choose a writable location for your toolbits") while not dirOK(): workingdir = PySide.QtGui.QFileDialog.getExistingDirectory( - None, msg, PathPreferences.filePath() + None, msg, Path.Preferences.filePath() ) if workingdir[-8:] == os.path.sep + "Library": workingdir = workingdir[:-8] # trim off trailing /Library if user chose it - PathPreferences.setLastPathToolLibrary( + Path.Preferences.setLastPathToolLibrary( "{}{}Library".format(workingdir, os.path.sep) ) - PathPreferences.setLastPathToolBit("{}{}Bit".format(workingdir, os.path.sep)) - PathLog.debug("setting workingdir to: {}".format(workingdir)) + Path.Preferences.setLastPathToolBit("{}{}Bit".format(workingdir, os.path.sep)) + Path.Log.debug("setting workingdir to: {}".format(workingdir)) - # Copy only files of default Path\Tools folder to working directory (targeting the README.md help file) + # Copy only files of default Path/Tool folder to working directory (targeting the README.md help file) src_toolfiles = os.listdir(defaultdir) for file_name in src_toolfiles: if file_name in ["README.md"]: @@ -154,14 +153,14 @@ def checkWorkingDir(): shutil.copy(full_file_name, subdir) # if no library is set, choose the first one in the Library directory - if PathPreferences.lastFileToolLibrary() is None: + if Path.Preferences.lastFileToolLibrary() is None: libFiles = [ f for f in glob.glob( - PathPreferences.lastPathToolLibrary() + os.path.sep + "*.fctl" + Path.Preferences.lastPathToolLibrary() + os.path.sep + "*.fctl" ) ] - PathPreferences.setLastFileToolLibrary(libFiles[0]) + Path.Preferences.setLastFileToolLibrary(libFiles[0]) return True @@ -221,7 +220,7 @@ class _TableView(PySide.QtGui.QTableView): self._copyTool(uuid, dst + i) def dropEvent(self, event): - PathLog.track() + Path.Log.track() mime = event.mimeData() data = mime.data("application/x-qstandarditemmodeldatalist") stream = PySide.QtCore.QDataStream(data) @@ -245,13 +244,13 @@ class ModelFactory(object): """Helper class to generate qtdata models for toolbit libraries""" def __init__(self, path=None): - PathLog.track() + Path.Log.track() self.path = "" # self.currentLib = "" def __libraryLoad(self, path, datamodel): - PathLog.track(path) - PathPreferences.setLastFileToolLibrary(path) + Path.Log.track(path) + Path.Preferences.setLastFileToolLibrary(path) # self.currenLib = path with open(path) as fp: @@ -262,11 +261,11 @@ class ModelFactory(object): nr = toolBit["nr"] bit = PathToolBit.findToolBit(toolBit["path"], path) if bit: - PathLog.track(bit) + Path.Log.track(bit) tool = PathToolBit.Declaration(bit) datamodel.appendRow(self._toolAdd(nr, tool, bit)) else: - PathLog.error( + Path.Log.error( "Could not find tool #{}: {}".format(nr, toolBit["path"]) ) except Exception as e: @@ -301,7 +300,7 @@ class ModelFactory(object): """ Adds a toolbit item to a model """ - PathLog.track() + Path.Log.track() try: nr = 0 @@ -311,7 +310,7 @@ class ModelFactory(object): nr += 1 tool = PathToolBit.Declaration(path) except Exception as e: - PathLog.error(e) + Path.Log.error(e) datamodel.appendRow(self._toolAdd(nr, tool, path)) @@ -320,8 +319,8 @@ class ModelFactory(object): Finds all the fctl files in a location Returns a QStandardItemModel """ - PathLog.track() - path = PathPreferences.lastPathToolLibrary() + Path.Log.track() + path = Path.Preferences.lastPathToolLibrary() if os.path.isdir(path): # opening all tables in a directory libFiles = [f for f in glob.glob(path + os.path.sep + "*.fctl")] @@ -335,7 +334,7 @@ class ModelFactory(object): libItem.setIcon(PySide.QtGui.QPixmap(":/icons/Path_ToolTable.svg")) model.appendRow(libItem) - PathLog.debug("model rows: {}".format(model.rowCount())) + Path.Log.debug("model rows: {}".format(model.rowCount())) return model def libraryOpen(self, model, lib=""): @@ -343,10 +342,10 @@ class ModelFactory(object): opens the tools in library Returns a QStandardItemModel """ - PathLog.track(lib) + Path.Log.track(lib) if lib == "": - lib = PathPreferences.lastFileToolLibrary() + lib = Path.Preferences.lastFileToolLibrary() if lib == "" or lib is None: return model @@ -354,7 +353,7 @@ class ModelFactory(object): if os.path.isfile(lib): # An individual library is wanted self.__libraryLoad(lib, model) - PathLog.debug("model rows: {}".format(model.rowCount())) + Path.Log.debug("model rows: {}".format(model.rowCount())) return model @@ -373,7 +372,7 @@ class ToolBitSelector(object): return ["#", "Tool"] def currentLibrary(self, shortNameOnly): - libfile = PathPreferences.lastFileToolLibrary() + libfile = Path.Preferences.lastFileToolLibrary() if libfile is None or libfile == "": return "" elif shortNameOnly: @@ -381,7 +380,7 @@ class ToolBitSelector(object): return libfile def loadData(self): - PathLog.track() + Path.Log.track() self.toolModel.clear() self.toolModel.setHorizontalHeaderLabels(self.columnNames()) self.form.lblLibrary.setText(self.currentLibrary(True)) @@ -391,7 +390,7 @@ class ToolBitSelector(object): self.toolModel.takeColumn(2) def setupUI(self): - PathLog.track() + Path.Log.track() self.loadData() self.form.tools.setModel(self.toolModel) self.form.tools.selectionModel().selectionChanged.connect(self.enableButtons) @@ -491,7 +490,7 @@ class ToolBitLibrary(object): displaying/selecting/creating/editing a collection of ToolBits.""" def __init__(self): - PathLog.track() + Path.Log.track() checkWorkingDir() self.factory = ModelFactory() self.temptool = None @@ -507,7 +506,7 @@ class ToolBitLibrary(object): self.title = self.form.windowTitle() def toolBitNew(self): - PathLog.track() + Path.Log.track() # select the shape file shapefile = PathToolBitGui.GetToolShapeFile() @@ -523,7 +522,7 @@ class ToolBitLibrary(object): loc, fil = os.path.split(filename) fname = os.path.splitext(fil)[0] fullpath = "{}{}{}.fctb".format(loc, os.path.sep, fname) - PathLog.debug("fullpath: {}".format(fullpath)) + Path.Log.debug("fullpath: {}".format(fullpath)) self.temptool = PathToolBit.ToolBitFactory().Create(name=fname) self.temptool.BitShape = shapefile @@ -552,7 +551,7 @@ class ToolBitLibrary(object): self.factory.newTool(self.toolModel, fullpath) def toolDelete(self): - PathLog.track() + Path.Log.track() selectedRows = set( [index.row() for index in self.toolTableView.selectedIndexes()] ) @@ -565,25 +564,25 @@ class ToolBitLibrary(object): def tableSelected(self, index): """loads the tools for the selected tool table""" - PathLog.track() + Path.Log.track() item = index.model().itemFromIndex(index) libpath = item.data(_PathRole) self.loadData(libpath) self.path = libpath def open(self): - PathLog.track() + Path.Log.track() return self.form.exec_() def libraryPath(self): - PathLog.track() + Path.Log.track() path = PySide.QtGui.QFileDialog.getExistingDirectory( - self.form, "Tool Library Path", PathPreferences.lastPathToolLibrary() + self.form, "Tool Library Path", Path.Preferences.lastPathToolLibrary() ) if len(path) == 0: return - PathPreferences.setLastPathToolLibrary(path) + Path.Preferences.setLastPathToolLibrary(path) self.loadData() def cleanupDocument(self): @@ -632,7 +631,7 @@ class ToolBitLibrary(object): self.form.librarySave.setEnabled(True) def toolEdit(self, selected): - PathLog.track() + Path.Log.track() item = self.toolModel.item(selected.row(), 0) if self.temptool is not None: @@ -669,7 +668,7 @@ class ToolBitLibrary(object): filename = PySide.QtGui.QFileDialog.getSaveFileName( self.form, translate("Path_ToolBit", "Save toolbit library"), - PathPreferences.lastPathToolLibrary(), + Path.Preferences.lastPathToolLibrary(), "{}".format(TooltableTypeJSON), ) @@ -700,7 +699,7 @@ class ToolBitLibrary(object): self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole ) toolPath = self.toolModel.data(self.toolModel.index(row, 0), _PathRole) - if PathPreferences.toolsStoreAbsolutePaths(): + if Path.Preferences.toolsStoreAbsolutePaths(): bitPath = toolPath else: # bitPath = PathToolBit.findRelativePathTool(toolPath) @@ -720,17 +719,17 @@ class ToolBitLibrary(object): self.form.close() def libPaths(self): - lib = PathPreferences.lastFileToolLibrary() - loc = PathPreferences.lastPathToolLibrary() + lib = Path.Preferences.lastFileToolLibrary() + loc = Path.Preferences.lastPathToolLibrary() - PathLog.track("lib: {} loc: {}".format(lib, loc)) + Path.Log.track("lib: {} loc: {}".format(lib, loc)) return lib, loc def columnNames(self): return ["Nr", "Tool", "Shape"] def loadData(self, path=None): - PathLog.track(path) + Path.Log.track(path) self.toolTableView.setUpdatesEnabled(False) self.form.TableList.setUpdatesEnabled(False) @@ -747,7 +746,7 @@ class ToolBitLibrary(object): self.factory.libraryOpen(self.toolModel, lib=path) self.path = path - self.form.setWindowTitle("{}".format(PathPreferences.lastPathToolLibrary())) + self.form.setWindowTitle("{}".format(Path.Preferences.lastPathToolLibrary())) self.toolModel.setHorizontalHeaderLabels(self.columnNames()) self.listModel.setHorizontalHeaderLabels(["Library"]) @@ -766,7 +765,7 @@ class ToolBitLibrary(object): self.form.TableList.setUpdatesEnabled(True) def setupUI(self): - PathLog.track() + Path.Log.track() self.form.TableList.setModel(self.listModel) self.toolTableView.setModel(self.toolModel) @@ -799,7 +798,7 @@ class ToolBitLibrary(object): filename = PySide.QtGui.QFileDialog.getSaveFileName( self.form, translate("Path_ToolBit", "Save toolbit library"), - PathPreferences.lastPathToolLibrary(), + Path.Preferences.lastPathToolLibrary(), "{};;{};;{}".format( TooltableTypeJSON, TooltableTypeLinuxCNC, TooltableTypeCamotics ), @@ -843,7 +842,7 @@ class ToolBitLibrary(object): bit = PathToolBit.Factory.CreateFrom(toolPath) if bit: - PathLog.track(bit) + Path.Log.track(bit) pocket = bit.Pocket if hasattr(bit, "Pocket") else "0" xoffset = bit.Xoffset if hasattr(bit, "Xoffset") else "0" @@ -893,7 +892,7 @@ class ToolBitLibrary(object): FreeCAD.ActiveDocument.removeObject(bit.Name) else: - PathLog.error("Could not find tool #{} ".format(toolNr)) + Path.Log.error("Could not find tool #{} ".format(toolNr)) def libararySaveCamotics(self, path): @@ -923,7 +922,7 @@ class ToolBitLibrary(object): ) toolPath = self.toolModel.data(self.toolModel.index(row, 0), _PathRole) - PathLog.debug(toolPath) + Path.Log.debug(toolPath) try: bit = PathToolBit.Factory.CreateFrom(toolPath) except FileNotFoundError as e: @@ -935,7 +934,7 @@ class ToolBitLibrary(object): if not bit: continue - PathLog.track(bit) + Path.Log.track(bit) toolitem = tooltemplate.copy() diff --git a/src/Mod/Path/PathScripts/PathToolBitLibraryCmd.py b/src/Mod/Path/Path/Tool/Gui/BitLibraryCmd.py similarity index 90% rename from src/Mod/Path/PathScripts/PathToolBitLibraryCmd.py rename to src/Mod/Path/Path/Tool/Gui/BitLibraryCmd.py index 309f77d5e9..d141894220 100644 --- a/src/Mod/Path/PathScripts/PathToolBitLibraryCmd.py +++ b/src/Mod/Path/Path/Tool/Gui/BitLibraryCmd.py @@ -23,13 +23,13 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import FreeCADGui -import PathScripts.PathLog as PathLog +import Path if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -55,7 +55,7 @@ class CommandToolBitSelectorOpen: return FreeCAD.ActiveDocument is not None def Activated(self): - import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui + import Path.Tool.Gui.BitLibrary as PathToolBitLibraryGui dock = PathToolBitLibraryGui.ToolBitSelector() dock.open() @@ -85,7 +85,7 @@ class CommandToolBitLibraryOpen: return FreeCAD.ActiveDocument is not None def Activated(self): - import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui + import Path.Tool.Gui.BitLibrary as PathToolBitLibraryGui library = PathToolBitLibraryGui.ToolBitLibrary() diff --git a/src/Mod/Path/PathScripts/PathToolControllerGui.py b/src/Mod/Path/Path/Tool/Gui/Controller.py similarity index 86% rename from src/Mod/Path/PathScripts/PathToolControllerGui.py rename to src/Mod/Path/Path/Tool/Gui/Controller.py index 72e4445c7b..630741908a 100644 --- a/src/Mod/Path/PathScripts/PathToolControllerGui.py +++ b/src/Mod/Path/Path/Tool/Gui/Controller.py @@ -24,13 +24,12 @@ from PySide import QtCore, QtGui from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts -import PathScripts.PathGui as PathGui -import PathScripts.PathLog as PathLog -import PathScripts.PathToolBitGui as PathToolBitGui -import PathScripts.PathToolEdit as PathToolEdit -import PathScripts.PathUtil as PathUtil +import Path +import Path.Base.Gui.Util as PathGuiUtil +import Path.Base.Util as PathUtil +import Path.Tool.Controller as PathToolController +import Path.Tool.Gui.Bit as PathToolBitGui +import PathGui # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -39,10 +38,10 @@ Part = LazyLoader("Part", globals(), "Part") if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -111,7 +110,7 @@ class ViewProvider: return False def setupContextMenu(self, vobj, menu): - PathLog.track() + Path.Log.track() for action in menu.actions(): menu.removeAction(action) action = QtGui.QAction(translate("Path", "Edit"), menu) @@ -120,20 +119,19 @@ class ViewProvider: def claimChildren(self): obj = self.vobj.Object - if obj and obj.Proxy and not obj.Proxy.usesLegacyTool(obj): + if obj and obj.Proxy and obj.Tool: return [obj.Tool] return [] def Create(name="Default Tool", tool=None, toolNumber=1): - PathLog.track(tool, toolNumber) + Path.Log.track(tool, toolNumber) - obj = PathScripts.PathToolController.Create(name, tool, toolNumber) + obj = PathToolController.Create(name, tool, toolNumber) ViewProvider(obj.ViewObject) - if not obj.Proxy.usesLegacyTool(obj): - # ToolBits are visible by default, which is typically not what the user wants - if tool and tool.ViewObject and tool.ViewObject.Visibility: - tool.ViewObject.Visibility = False + # ToolBits are visible by default, which is typically not what the user wants + if tool and tool.ViewObject and tool.ViewObject.Visibility: + tool.ViewObject.Visibility = False return obj @@ -161,7 +159,7 @@ class CommandPathToolController(object): return self.selectedJob() is not None def Activated(self): - PathLog.track() + Path.Log.track() job = self.selectedJob() if job: tool = PathToolBitGui.ToolBitSelector().getTool() @@ -186,24 +184,21 @@ class ToolControllerEditor(object): self.obj = obj comboToPropertyMap = [("spindleDirection", "SpindleDir")] - enumTups = PathScripts.PathToolController.ToolController.propertyEnumerations( + enumTups = PathToolController.ToolController.propertyEnumerations( dataType="raw" ) - PathGui.populateCombobox(self.form, enumTups, comboToPropertyMap) - self.vertFeed = PathGui.QuantitySpinBox(self.form.vertFeed, obj, "VertFeed") - self.horizFeed = PathGui.QuantitySpinBox(self.form.horizFeed, obj, "HorizFeed") - self.vertRapid = PathGui.QuantitySpinBox(self.form.vertRapid, obj, "VertRapid") - self.horizRapid = PathGui.QuantitySpinBox( + PathGuiUtil.populateCombobox(self.form, enumTups, comboToPropertyMap) + self.vertFeed = PathGuiUtil.QuantitySpinBox(self.form.vertFeed, obj, "VertFeed") + self.horizFeed = PathGuiUtil.QuantitySpinBox(self.form.horizFeed, obj, "HorizFeed") + self.vertRapid = PathGuiUtil.QuantitySpinBox(self.form.vertRapid, obj, "VertRapid") + self.horizRapid = PathGuiUtil.QuantitySpinBox( self.form.horizRapid, obj, "HorizRapid" ) - if obj.Proxy.usesLegacyTool(obj): - self.editor = PathToolEdit.ToolEditor(obj.Tool, self.form.toolEditor) - else: - self.editor = None - self.form.toolBox.widget(1).hide() - self.form.toolBox.removeItem(1) + self.editor = None + self.form.toolBox.widget(1).hide() + self.form.toolBox.removeItem(1) def selectInComboBox(self, name, combo): """selectInComboBox(name, combo) ... @@ -265,7 +260,7 @@ class ToolControllerEditor(object): tc.Tool = self.editor.tool except Exception as e: - PathLog.error("Error updating TC: {}".format(e)) + Path.Log.error("Error updating TC: {}".format(e)) def refresh(self): self.form.blockSignals(True) @@ -353,7 +348,7 @@ class DlgToolControllerEdit: rc = False if not self.editor.form.exec_(): - PathLog.info("revert") + Path.Log.info("revert") self.obj.Proxy.setFromTemplate(self.obj, restoreTC) rc = True return rc diff --git a/src/Mod/Path/Path/Tool/Gui/__init__.py b/src/Mod/Path/Path/Tool/Gui/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/Path/Tool/__init__.py b/src/Mod/Path/Path/Tool/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Path/Path/__init__.py b/src/Mod/Path/Path/__init__.py new file mode 100644 index 0000000000..d3104b93f8 --- /dev/null +++ b/src/Mod/Path/Path/__init__.py @@ -0,0 +1,5 @@ +from PathApp import * + +import Path.Log as Log +import Path.Geom as Geom +import Path.Preferences as Preferences diff --git a/src/Mod/Path/PathCommands.py b/src/Mod/Path/PathCommands.py index 725f27bf27..e42c995038 100644 --- a/src/Mod/Path/PathCommands.py +++ b/src/Mod/Path/PathCommands.py @@ -21,8 +21,8 @@ # *************************************************************************** import FreeCAD +import Path import PathScripts -import PathScripts.PathLog as PathLog import traceback from PathScripts.PathUtils import loopdetect @@ -80,7 +80,7 @@ class _CommandSelectLoop: self.active = False return self.active except Exception as exc: - PathLog.error(exc) + Path.Log.error(exc) traceback.print_exc(exc) return False @@ -161,10 +161,10 @@ class _ToggleOperation: return False try: for sel in FreeCADGui.Selection.getSelectionEx(): - selProxy = PathScripts.PathDressup.baseOp(sel.Object).Proxy + selProxy = Path.Dressup.Utils.baseOp(sel.Object).Proxy if not isinstance( - selProxy, PathScripts.PathOp.ObjectOp - ) and not isinstance(selProxy, PathScripts.PathArray.ObjectArray): + selProxy, Path.Op.Base.ObjectOp + ) and not isinstance(selProxy, Path.Op.Gui.Array.ObjectArray): return False return True except (IndexError, AttributeError): @@ -172,7 +172,7 @@ class _ToggleOperation: def Activated(self): for sel in FreeCADGui.Selection.getSelectionEx(): - op = PathScripts.PathDressup.baseOp(sel.Object) + op = Path.Dressup.Utils.baseOp(sel.Object) op.Active = not op.Active op.ViewObject.Visibility = op.Active @@ -203,7 +203,7 @@ class _CopyOperation: return False try: for sel in FreeCADGui.Selection.getSelectionEx(): - if not isinstance(sel.Object.Proxy, PathScripts.PathOp.ObjectOp): + if not isinstance(sel.Object.Proxy, Path.Op.Base.ObjectOp): return False return True except (IndexError, AttributeError): diff --git a/src/Mod/Path/PathScripts/PathCollision.py b/src/Mod/Path/PathScripts/PathCollision.py deleted file mode 100644 index 645c16b96a..0000000000 --- a/src/Mod/Path/PathScripts/PathCollision.py +++ /dev/null @@ -1,127 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2017 sliptonic * -# * * -# * 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 -import PathScripts.PathLog as PathLog -from PySide import QtCore -from PathScripts.PathUtils import waiting_effects -from PySide.QtCore import QT_TRANSLATE_NOOP - -LOG_MODULE = "PathCollision" -PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE) -PathLog.trackModule("PathCollision") -FreeCAD.setLogLevel("Path.Area", 0) - -__title__ = "Path Collision Utility" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" - -"""Path Collision object and FreeCAD command""" - - -class _CollisionSim: - def __init__(self, obj): - obj.Proxy = self - - def execute(self, fp): - """Do something when doing a recomputation, this method is mandatory""" - print("_CollisionSim", fp) - - -class _ViewProviderCollisionSim: - def __init__(self, vobj): - self.Object = vobj.Object - vobj.Proxy = self - vobj.addProperty( - "App::PropertyLink", - "Original", - "reference", - QT_TRANSLATE_NOOP( - "App::Property", "The base object this collision refers to" - ), - ) - - def attach(self, vobj): - self.Object = vobj.Object - - def setEdit(self, vobj, mode=0): - return True - - def getIcon(self): - return ":/icons/Path_Contour.svg" - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - def onDelete(self, feature, subelements): - feature.Original.ViewObject.Visibility = True - return True - - -def __compareBBSpace(bb1, bb2): - if ( - bb1.XMin == bb2.XMin - and bb1.XMax == bb2.XMax - and bb1.YMin == bb2.YMin - and bb1.YMax == bb2.YMax - and bb1.ZMin == bb2.ZMin - and bb1.ZMax == bb2.ZMax - ): - return True - return False - - -@waiting_effects -def getCollisionObject(baseobject, simobject): - result = None - cVol = baseobject.Shape.common(simobject) - if cVol.Volume > 1e-12: - baseColor = (0.800000011920929, 0.800000011920929, 0.800000011920929, 00.0) - intersecColor = (1.0, 0.0, 0.0, 0.0) - colorassignment = [] - gougedShape = baseobject.Shape.cut(simobject) - - for i in gougedShape.Faces: - match = False - for j in cVol.Faces: - if __compareBBSpace(i.BoundBox, j.BoundBox): - match = True - if match is True: - # print ("Need to highlight Face{}".format(idx+1)) - colorassignment.append(intersecColor) - else: - colorassignment.append(baseColor) - - obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Collision") - obj.Shape = gougedShape - _CollisionSim(obj) - _ViewProviderCollisionSim(obj.ViewObject) - - obj.ViewObject.DiffuseColor = colorassignment - FreeCAD.ActiveDocument.recompute() - baseobject.ViewObject.Visibility = False - obj.ViewObject.Original = baseobject - - return result diff --git a/src/Mod/Path/PathScripts/PathDressupTag.py b/src/Mod/Path/PathScripts/PathDressupTag.py deleted file mode 100644 index 6a9487adea..0000000000 --- a/src/Mod/Path/PathScripts/PathDressupTag.py +++ /dev/null @@ -1,318 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2017 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** - -from PathScripts.PathDressupTagPreferences import HoldingTagPreferences -from PySide.QtCore import QT_TRANSLATE_NOOP -import FreeCAD -import PathScripts.PathDressup as PathDressup -import PathScripts.PathGeom as PathGeom -import PathScripts.PathLog as PathLog -import PathScripts.PathUtils as PathUtils -import math - -# lazily loaded modules -from lazy_loader.lazy_loader import LazyLoader - -DraftGeomUtils = LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") -Part = LazyLoader("Part", globals(), "Part") - - -if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) -else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) - -translate = FreeCAD.Qt.translate - - -MaxInt = 99999999999999 - - -class TagSolid: - def __init__(self, proxy, z, R): - self.proxy = proxy - self.z = z - self.toolRadius = R - self.angle = math.fabs(proxy.obj.Angle) - self.width = math.fabs(proxy.obj.Width) - self.height = math.fabs(proxy.obj.Height) - self.radius = math.fabs(proxy.obj.Radius) - self.actualHeight = self.height - self.fullWidth = 2 * self.toolRadius + self.width - - r1 = self.fullWidth / 2 - self.r1 = r1 - self.r2 = r1 - height = self.actualHeight * 1.01 - radius = 0 - if self.angle == 90 and height > 0: - # cylinder - self.solid = Part.makeCylinder(r1, height) - radius = min(min(self.radius, r1), self.height) - PathLog.debug("Part.makeCylinder(%f, %f)" % (r1, height)) - elif self.angle > 0.0 and height > 0.0: - # cone - rad = math.radians(self.angle) - tangens = math.tan(rad) - dr = height / tangens - if dr < r1: - # with top - r2 = r1 - dr - s = height / math.sin(rad) - radius = min(r2, s) * math.tan((math.pi - rad) / 2) * 0.95 - else: - # triangular - r2 = 0 - height = r1 * tangens * 1.01 - self.actualHeight = height - self.r2 = r2 - PathLog.debug("Part.makeCone(r1=%.2f, r2=%.2f, h=%.2f)" % (r1, r2, height)) - self.solid = Part.makeCone(r1, r2, height) - else: - # degenerated case - no tag - PathLog.debug("Part.makeSphere(%.2f)" % (r1 / 10000)) - self.solid = Part.makeSphere(r1 / 10000) - - radius = min(self.radius, radius) - self.realRadius = radius - if radius != 0: - PathLog.debug("makeFillet(%.4f)" % radius) - self.solid = self.solid.makeFillet(radius, [self.solid.Edges[0]]) - - # lastly determine the center of the model, we want to make sure the seam of - # the tag solid points away (in the hopes it doesn't coincide with a path) - self.baseCenter = FreeCAD.Vector( - (proxy.ptMin.x + proxy.ptMax.x) / 2, (proxy.ptMin.y + proxy.ptMax.y) / 2, 0 - ) - - def cloneAt(self, pos): - clone = self.solid.copy() - pos.z = 0 - angle = -PathGeom.getAngle(pos - self.baseCenter) * 180 / math.pi - clone.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), angle) - pos.z = self.z - self.actualHeight * 0.01 - clone.translate(pos) - return clone - - -class ObjectDressup: - def __init__(self, obj, base): - - obj.addProperty( - "App::PropertyLink", - "Base", - "Base", - QT_TRANSLATE_NOOP("App::Property", "The base path to modify"), - ) - obj.addProperty( - "App::PropertyLength", - "Width", - "Tag", - QT_TRANSLATE_NOOP("App::Property", "Width of tags."), - ) - obj.addProperty( - "App::PropertyLength", - "Height", - "Tag", - QT_TRANSLATE_NOOP("App::Property", "Height of tags."), - ) - obj.addProperty( - "App::PropertyAngle", - "Angle", - "Tag", - QT_TRANSLATE_NOOP("App::Property", "Angle of tag plunge and ascent."), - ) - obj.addProperty( - "App::PropertyLength", - "Radius", - "Tag", - QT_TRANSLATE_NOOP("App::Property", "Radius of the fillet for the tag."), - ) - obj.addProperty( - "App::PropertyVectorList", - "Positions", - "Tag", - QT_TRANSLATE_NOOP("App::Property", "Locations of inserted holding tags"), - ) - obj.addProperty( - "App::PropertyIntegerList", - "Disabled", - "Tag", - QT_TRANSLATE_NOOP("App::Property", "IDs of disabled holding tags"), - ) - obj.addProperty( - "App::PropertyInteger", - "SegmentationFactor", - "Tag", - QT_TRANSLATE_NOOP( - "App::Property", - "Factor determining the # of segments used to approximate rounded tags.", - ), - ) - - obj.Proxy = self - obj.Base = base - - self.obj = obj - self.solids = [] - - # initialized later - self.edges = None - self.masterSolid = None - self.ptMax = None - self.ptMin = None - self.tagSolid = None - self.wire = None - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - def assignDefaultValues(self): - self.obj.Width = HoldingTagPreferences.defaultWidth(self.toolRadius() * 2) - self.obj.Height = HoldingTagPreferences.defaultHeight(self.toolRadius()) - self.obj.Angle = HoldingTagPreferences.defaultAngle() - self.obj.Radius = HoldingTagPreferences.defaultRadius() - - def execute(self, obj): - PathLog.track() - if not obj.Base: - PathLog.error(translate("Path_DressupTag", "No Base object found.")) - return - if not obj.Base.isDerivedFrom("Path::Feature"): - PathLog.error( - translate("Path_DressupTag", "Base is not a Path::Feature object.") - ) - return - if not obj.Base.Path: - PathLog.error( - translate("Path_DressupTag", "Base doesn't have a Path to dress-up.") - ) - return - if not obj.Base.Path.Commands: - PathLog.error(translate("Path_DressupTag", "Base Path is empty.")) - return - - self.obj = obj - - minZ = +MaxInt - minX = minZ - minY = minZ - - maxZ = -MaxInt - maxX = maxZ - maxY = maxZ - - # the assumption is that all helixes are in the xy-plane - in other words there is no - # intermittent point of a command that has a lower/higher Z-position than the start and - # and end positions of a command. - lastPt = FreeCAD.Vector(0, 0, 0) - for cmd in obj.Base.Path.Commands: - pt = PathGeom.commandEndPoint(cmd, lastPt) - if lastPt.x != pt.x: - maxX = max(pt.x, maxX) - minX = min(pt.x, minX) - if lastPt.y != pt.y: - maxY = max(pt.y, maxY) - minY = min(pt.y, minY) - if lastPt.z != pt.z: - maxZ = max(pt.z, maxZ) - minZ = min(pt.z, minZ) - lastPt = pt - PathLog.debug( - "bb = (%.2f, %.2f, %.2f) ... (%.2f, %.2f, %.2f)" - % (minX, minY, minZ, maxX, maxY, maxZ) - ) - self.ptMin = FreeCAD.Vector(minX, minY, minZ) - self.ptMax = FreeCAD.Vector(maxX, maxY, maxZ) - self.masterSolid = TagSolid(self, minZ, self.toolRadius()) - self.solids = [self.masterSolid.cloneAt(pos) for pos in self.obj.Positions] - self.tagSolid = Part.Compound(self.solids) - - self.wire, rapid = PathGeom.wireForPath(obj.Base.Path) - self.edges = self.wire.Edges - - maxTagZ = minZ + obj.Height.Value - - # lastX = 0 - # lastY = 0 - lastZ = 0 - - commands = [] - - for cmd in obj.Base.Path.Commands: - if cmd in PathGeom.CmdMove: - if lastZ <= maxTagZ or cmd.Parameters.get("Z", lastZ) <= maxTagZ: - pass - else: - commands.append(cmd) - else: - commands.append(cmd) - - obj.Path = obj.Base.Path - - PathLog.track() - - def toolRadius(self): - return float(PathDressup.toolController(self.obj.Base).Tool.Diameter) / 2.0 - - def addTagsToDocument(self): - for i, solid in enumerate(self.solids): - obj = FreeCAD.ActiveDocument.addObject("Part::Compound", "tag_%02d" % i) - obj.Shape = solid - - def supportsTagGeneration(self, obj): - return False - - def pointIsOnPath(self, obj, p): - for e in self.edges: - if DraftGeomUtils.isPtOnEdge(p, e): - return True - return False - - -def Create(baseObject, name="DressupTag"): - """ - Create(basePath, name = 'DressupTag') ... create tag dressup object for the given base path. - """ - if not baseObject.isDerivedFrom("Path::Feature"): - PathLog.error( - translate("Path_DressupTag", "The selected object is not a path") + "\n" - ) - return None - - if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): - PathLog.error(translate("Path_DressupTag", "Please select a Profile object")) - return None - - obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) - dbo = ObjectDressup(obj, baseObject) - job = PathUtils.findParentJob(baseObject) - job.addOperation(obj) - dbo.assignDefaultValues() - return obj - - -PathLog.notice("Loading Path_DressupTag... done\n") diff --git a/src/Mod/Path/PathScripts/PathPlane.py b/src/Mod/Path/PathScripts/PathPlane.py deleted file mode 100644 index 9db418952d..0000000000 --- a/src/Mod/Path/PathScripts/PathPlane.py +++ /dev/null @@ -1,156 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2015 Dan Falck * -# * * -# * 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 * -# * * -# *************************************************************************** - -""" Used for CNC machine plane selection G17,G18,G19 """ - -import FreeCAD -import FreeCADGui -import Path -from PySide import QtCore -from PySide.QtCore import QT_TRANSLATE_NOOP - - -class Plane: - def __init__(self, obj): - obj.addProperty( - "App::PropertyEnumeration", - "SelectionPlane", - "Path", - QT_TRANSLATE_NOOP("App::Property", "Orientation plane of CNC path"), - ) - obj.SelectionPlane = ["XY", "XZ", "YZ"] - obj.addProperty( - "App::PropertyBool", - "Active", - "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Make False, to prevent operation from generating code" - ), - ) - obj.Proxy = self - - def execute(self, obj): - clonelist = ["XY", "XZ", "YZ"] - cindx = clonelist.index(str(obj.SelectionPlane)) - pathlist = ["G17", "G18", "G19"] - labelindx = clonelist.index(obj.SelectionPlane) + 1 - obj.Label = "Plane" + str(labelindx) - if obj.Active: - obj.Path = Path.Path(pathlist[cindx]) - obj.ViewObject.Visibility = True - else: - obj.Path = Path.Path("(inactive operation)") - obj.ViewObject.Visibility = False - - -class _ViewProviderPlane: - def __init__(self, vobj): # mandatory - vobj.Proxy = self - mode = 2 - vobj.setEditorMode("LineWidth", mode) - vobj.setEditorMode("MarkerColor", mode) - vobj.setEditorMode("NormalColor", mode) - vobj.setEditorMode("DisplayMode", mode) - vobj.setEditorMode("BoundingBox", mode) - vobj.setEditorMode("Selectable", mode) - vobj.setEditorMode("ShapeColor", mode) - vobj.setEditorMode("Transparency", mode) - vobj.setEditorMode("Visibility", mode) - - def __getstate__(self): # mandatory - return None - - def __setstate__(self, state): # mandatory - return None - - def getIcon(self): # optional - return ":/icons/Path_Plane.svg" - - def onChanged(self, vobj, prop): # optional - mode = 2 - vobj.setEditorMode("LineWidth", mode) - vobj.setEditorMode("MarkerColor", mode) - vobj.setEditorMode("NormalColor", mode) - vobj.setEditorMode("DisplayMode", mode) - vobj.setEditorMode("BoundingBox", mode) - vobj.setEditorMode("Selectable", mode) - vobj.setEditorMode("ShapeColor", mode) - vobj.setEditorMode("Transparency", mode) - vobj.setEditorMode("Visibility", mode) - - def updateData(self, vobj, prop): # optional - # this is executed when a property of the APP OBJECT changes - pass - - def setEdit(self, vobj, mode): # optional - # this is executed when the object is double-clicked in the tree - pass - - def unsetEdit(self, vobj, mode): # optional - # this is executed when the user cancels or terminates edit mode - pass - - -class CommandPathPlane: - def GetResources(self): - return { - "Pixmap": "PathPlane", - "MenuText": QT_TRANSLATE_NOOP("PathPlane", "Selection Plane"), - "ToolTip": QT_TRANSLATE_NOOP( - "PathPlane", "Create a Selection Plane object" - ), - } - - def IsActive(self): - if FreeCAD.ActiveDocument is not None: - for o in FreeCAD.ActiveDocument.Objects: - if o.Name[:3] == "Job": - return True - return False - - def Activated(self): - FreeCAD.ActiveDocument.openTransaction("Create a Selection Plane object") - FreeCADGui.addModule("PathScripts.PathPlane") - snippet = """ -import Path -import PathScripts -from PathScripts import PathUtils -prjexists = False -obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Plane") -PathScripts.PathPlane.Plane(obj) -obj.Active = True -PathScripts.PathPlane._ViewProviderPlane(obj.ViewObject) -PathUtils.addToJob(obj) - -""" - - FreeCADGui.doCommand(snippet) - FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() - - -if FreeCAD.GuiUp: - # register the FreeCAD command - FreeCADGui.addCommand("Path_Plane", CommandPathPlane()) - - -FreeCAD.Console.PrintLog("Loading PathPlane... done\n") diff --git a/src/Mod/Path/PathScripts/PathProfileContour.py b/src/Mod/Path/PathScripts/PathProfileContour.py deleted file mode 100644 index 3d2ee44d6d..0000000000 --- a/src/Mod/Path/PathScripts/PathProfileContour.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2016 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** -# * Major modifications: 2020 Russell Johnson * - -import FreeCAD -import PathScripts.PathProfile as PathProfile - - -__title__ = "Path Contour Operation (depreciated)" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = "Implementation of the Contour operation (depreciated)." - - -class ObjectContour(PathProfile.ObjectProfile): - """Pseudo class for Profile operation, - allowing for backward compatibility with pre-existing "Contour" operations.""" - - pass - - -# Eclass - - -def SetupProperties(): - return PathProfile.SetupProperties() - - -def Create(name, obj=None, parentJob=None): - """Create(name) ... Creates and returns a Profile operation.""" - if obj is None: - obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) - obj.Proxy = ObjectContour(obj, name, parentJob) - return obj diff --git a/src/Mod/Path/PathScripts/PathProfileContourGui.py b/src/Mod/Path/PathScripts/PathProfileContourGui.py deleted file mode 100644 index 396d44b14a..0000000000 --- a/src/Mod/Path/PathScripts/PathProfileContourGui.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2017 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** -# * Major modifications: 2020 Russell Johnson * - -import FreeCAD -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathProfile as PathProfile -import PathScripts.PathProfileGui as PathProfileGui -from PySide.QtCore import QT_TRANSLATE_NOOP - -__title__ = "Path Contour Operation UI (depreciated)" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = "Contour operation page controller and command implementation (deprecated)." - - -class TaskPanelOpPage(PathProfileGui.TaskPanelOpPage): - """Pseudo page controller class for Profile operation, - allowing for backward compatibility with pre-existing "Contour" operations.""" - - pass - - -Command = PathOpGui.SetupOperation( - "Profile", - PathProfile.Create, - TaskPanelOpPage, - "Path_Contour", - QT_TRANSLATE_NOOP("Path_Profile", "Profile"), - QT_TRANSLATE_NOOP( - "Path_Profile", "Profile entire model, selected face(s) or selected edge(s)" - ), - PathProfile.SetupProperties, -) - -FreeCAD.Console.PrintLog("Loading PathProfileContourGui... done\n") diff --git a/src/Mod/Path/PathScripts/PathProfileEdges.py b/src/Mod/Path/PathScripts/PathProfileEdges.py deleted file mode 100644 index 12f487942f..0000000000 --- a/src/Mod/Path/PathScripts/PathProfileEdges.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2016 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** -# * Major modifications: 2020 Russell Johnson * - -import FreeCAD -import PathScripts.PathProfile as PathProfile - - -__title__ = "Path Profile Edges Operation (depreciated)" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = "Path Profile operation based on edges (depreciated)." -__contributors__ = "russ4262 (Russell Johnson)" - - -class ObjectProfile(PathProfile.ObjectProfile): - """Pseudo class for Profile operation, - allowing for backward compatibility with pre-existing "Profile Edges" operations.""" - - pass - - -# Eclass - - -def SetupProperties(): - return PathProfile.SetupProperties() - - -def Create(name, obj=None, parentJob=None): - """Create(name) ... Creates and returns a Profile operation.""" - if obj is None: - obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) - obj.Proxy = ObjectProfile(obj, name, parentJob) - return obj diff --git a/src/Mod/Path/PathScripts/PathProfileEdgesGui.py b/src/Mod/Path/PathScripts/PathProfileEdgesGui.py deleted file mode 100644 index 8a647e6b41..0000000000 --- a/src/Mod/Path/PathScripts/PathProfileEdgesGui.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2017 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** -# * Major modifications: 2020 Russell Johnson * - -import FreeCAD -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathProfile as PathProfile -import PathScripts.PathProfileGui as PathProfileGui -from PySide.QtCore import QT_TRANSLATE_NOOP - -__title__ = "Path Profile Edges Operation UI (depreciated)" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = ( - "Profile Edges operation page controller and command implementation (deprecated)." -) - - -class TaskPanelOpPage(PathProfileGui.TaskPanelOpPage): - """Pseudo page controller class for Profile operation, - allowing for backward compatibility with pre-existing "Profile Edges" operations.""" - - pass - - -Command = PathOpGui.SetupOperation( - "Profile", - PathProfile.Create, - TaskPanelOpPage, - "Path_Contour", - QT_TRANSLATE_NOOP("Path_Profile", "Profile"), - QT_TRANSLATE_NOOP( - "Path_Profile", "Profile entire model, selected face(s) or selected edge(s)" - ), - PathProfile.SetupProperties, -) - -FreeCAD.Console.PrintLog("Loading PathProfileEdgesGui... done\n") diff --git a/src/Mod/Path/PathScripts/PathProfileFaces.py b/src/Mod/Path/PathScripts/PathProfileFaces.py deleted file mode 100644 index 3de022ff57..0000000000 --- a/src/Mod/Path/PathScripts/PathProfileFaces.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2014 Yorik van Havre * -# * Copyright (c) 2020 Schildkroet * -# * * -# * 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 * -# * * -# *************************************************************************** -# * Major modifications: 2020 Russell Johnson * - -import FreeCAD -import PathScripts.PathProfile as PathProfile - - -__title__ = "Path Profile Faces Operation (depreciated)" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = "Path Profile operation based on faces (depreciated)." -__contributors__ = "Schildkroet" - - -class ObjectProfile(PathProfile.ObjectProfile): - """Pseudo class for Profile operation, - allowing for backward compatibility with pre-existing "Profile Faces" operations.""" - - pass - - -# Eclass - - -def SetupProperties(): - return PathProfile.SetupProperties() - - -def Create(name, obj=None, parentJob=None): - """Create(name) ... Creates and returns a Profile operation.""" - if obj is None: - obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) - obj.Proxy = ObjectProfile(obj, name, parentJob) - return obj diff --git a/src/Mod/Path/PathScripts/PathProfileFacesGui.py b/src/Mod/Path/PathScripts/PathProfileFacesGui.py deleted file mode 100644 index 90acd3837a..0000000000 --- a/src/Mod/Path/PathScripts/PathProfileFacesGui.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2017 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** -# * Major modifications: 2020 Russell Johnson * - -import FreeCAD -import PathScripts.PathOpGui as PathOpGui -import PathScripts.PathProfile as PathProfile -import PathScripts.PathProfileGui as PathProfileGui -from PySide.QtCore import QT_TRANSLATE_NOOP - -__title__ = "Path Profile Faces Operation UI (depreciated)" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = ( - "Profile Faces operation page controller and command implementation (deprecated)." -) - - -class TaskPanelOpPage(PathProfileGui.TaskPanelOpPage): - """Pseudo page controller class for Profile operation, - allowing for backward compatibility with pre-existing "Profile Faces" operations.""" - - pass - - -Command = PathOpGui.SetupOperation( - "Profile", - PathProfile.Create, - TaskPanelOpPage, - "Path_Contour", - QT_TRANSLATE_NOOP("Path_Profile", "Profile"), - QT_TRANSLATE_NOOP( - "Path_Profile", "Profile entire model, selected face(s) or selected edge(s)" - ), - PathProfile.SetupProperties, -) - -FreeCAD.Console.PrintLog("Loading PathProfileFacesGui... done\n") diff --git a/src/Mod/Path/PathScripts/PathPropertyBag.py b/src/Mod/Path/PathScripts/PathPropertyBag.py index 7238ec099b..fbd22e3e2f 100644 --- a/src/Mod/Path/PathScripts/PathPropertyBag.py +++ b/src/Mod/Path/PathScripts/PathPropertyBag.py @@ -1,150 +1,4 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2020 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** +# Do NOT remove! +# This establishes backwards compatibility with existing ToolBit files. -from PySide.QtCore import QT_TRANSLATE_NOOP -import FreeCAD -import re -import PathScripts.PathLog as PathLog - -__title__ = "Generic property container to store some values." -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = "A generic container for typed properties in arbitrary categories." - -if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) -else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) - - -translate = FreeCAD.Qt.translate - - -SupportedPropertyType = { - "Angle": "App::PropertyAngle", - "Bool": "App::PropertyBool", - "Distance": "App::PropertyDistance", - "Enumeration": "App::PropertyEnumeration", - "File": "App::PropertyFile", - "Float": "App::PropertyFloat", - "Integer": "App::PropertyInteger", - "Length": "App::PropertyLength", - "Percent": "App::PropertyPercent", - "String": "App::PropertyString", -} - - -def getPropertyTypeName(o): - for typ in SupportedPropertyType: - if SupportedPropertyType[typ] == o: - return typ - raise IndexError() - - -class PropertyBag(object): - """Property container object.""" - - CustomPropertyGroups = "CustomPropertyGroups" - CustomPropertyGroupDefault = "User" - - def __init__(self, obj): - obj.addProperty( - "App::PropertyStringList", - self.CustomPropertyGroups, - "Base", - QT_TRANSLATE_NOOP("App::Property", "List of custom property groups"), - ) - self.onDocumentRestored(obj) - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - def __sanitizePropertyName(self, name): - if len(name) == 0: - return - clean = name[0] - for i in range(1, len(name)): - if name[i] == " ": - clean += name[i + 1].upper() - i += 1 - elif name[i - 1] != " ": - clean += name[i] - return clean - - def onDocumentRestored(self, obj): - self.obj = obj - obj.setEditorMode(self.CustomPropertyGroups, 2) # hide - - def getCustomProperties(self): - """getCustomProperties() ... Return a list of all custom properties created in this container.""" - return [ - p - for p in self.obj.PropertiesList - if self.obj.getGroupOfProperty(p) in self.obj.CustomPropertyGroups - ] - - def addCustomProperty(self, propertyType, name, group=None, desc=None): - """addCustomProperty(propertyType, name, group=None, desc=None) ... adds a custom property and tracks its group.""" - if desc is None: - desc = "" - if group is None: - group = self.CustomPropertyGroupDefault - groups = self.obj.CustomPropertyGroups - - name = self.__sanitizePropertyName(name) - if not re.match("^[A-Za-z0-9_]*$", name): - raise ValueError("Property Name can only contain letters and numbers") - - if not group in groups: - groups.append(group) - self.obj.CustomPropertyGroups = groups - self.obj.addProperty(propertyType, name, group, desc) - return name - - def refreshCustomPropertyGroups(self): - """refreshCustomPropertyGroups() ... removes empty property groups, should be called after deleting properties.""" - customGroups = [] - for p in self.obj.PropertiesList: - group = self.obj.getGroupOfProperty(p) - if group in self.obj.CustomPropertyGroups and not group in customGroups: - customGroups.append(group) - self.obj.CustomPropertyGroups = customGroups - - -def Create(name="PropertyBag"): - obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", name) - obj.Proxy = PropertyBag(obj) - return obj - - -def IsPropertyBag(obj): - """Returns True if the supplied object is a property container (or its Proxy).""" - - if type(obj) == PropertyBag: - return True - if hasattr(obj, "Proxy"): - return IsPropertyBag(obj.Proxy) - return False +from Path.Base.PropertyBag import * diff --git a/src/Mod/Path/PathScripts/PathPropertyBagGui.py b/src/Mod/Path/PathScripts/PathPropertyBagGui.py index 07a1b31e68..5ed353dc6a 100644 --- a/src/Mod/Path/PathScripts/PathPropertyBagGui.py +++ b/src/Mod/Path/PathScripts/PathPropertyBagGui.py @@ -1,463 +1,4 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2020 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** +# Do NOT remove! +# This establishes backwards compatibility with existing ToolBit files. -from PySide import QtCore, QtGui -import FreeCAD -import FreeCADGui -import PathScripts.PathIconViewProvider as PathIconViewProvider -import PathScripts.PathLog as PathLog -import PathScripts.PathPropertyBag as PathPropertyBag -import PathScripts.PathPropertyEditor as PathPropertyEditor -import PathScripts.PathUtil as PathUtil -import re - - -__title__ = "Property Bag Editor" -__author__ = "sliptonic (Brad Collette)" -__url__ = "https://www.freecadweb.org" -__doc__ = "Task panel editor for a PropertyBag" - -if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) -else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) - -translate = FreeCAD.Qt.translate - - -class ViewProvider(object): - """ViewProvider for a PropertyBag. - It's sole job is to provide an icon and invoke the TaskPanel on edit.""" - - def __init__(self, vobj, name): - PathLog.track(name) - vobj.Proxy = self - self.icon = name - # mode = 2 - self.obj = None - self.vobj = None - - def attach(self, vobj): - PathLog.track() - self.vobj = vobj - self.obj = vobj.Object - - def getIcon(self): - return ":/icons/Path-SetupSheet.svg" - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - def getDisplayMode(self, mode): - return "Default" - - def setEdit(self, vobj, mode=0): - PathLog.track() - taskPanel = TaskPanel(vobj) - FreeCADGui.Control.closeDialog() - FreeCADGui.Control.showDialog(taskPanel) - taskPanel.setupUi() - return True - - def unsetEdit(self, vobj, mode): - FreeCADGui.Control.closeDialog() - return - - def claimChildren(self): - return [] - - def doubleClicked(self, vobj): - self.setEdit(vobj) - - -class Delegate(QtGui.QStyledItemDelegate): - RoleObject = QtCore.Qt.UserRole + 1 - RoleProperty = QtCore.Qt.UserRole + 2 - RoleEditor = QtCore.Qt.UserRole + 3 - - # def paint(self, painter, option, index): - # #PathLog.track(index.column(), type(option)) - - def createEditor(self, parent, option, index): - editor = PathPropertyEditor.Editor( - index.data(self.RoleObject), index.data(self.RoleProperty) - ) - index.model().setData(index, editor, self.RoleEditor) - return editor.widget(parent) - - def setEditorData(self, widget, index): - PathLog.track(index.row(), index.column()) - index.data(self.RoleEditor).setEditorData(widget) - - def setModelData(self, widget, model, index): - PathLog.track(index.row(), index.column()) - editor = index.data(self.RoleEditor) - editor.setModelData(widget) - index.model().setData(index, editor.displayString(), QtCore.Qt.DisplayRole) - - def updateEditorGeometry(self, widget, option, index): - widget.setGeometry(option.rect) - - -class PropertyCreate(object): - def __init__(self, obj, grp, typ, another): - self.obj = obj - self.form = FreeCADGui.PySideUic.loadUi(":panels/PropertyCreate.ui") - - obj.Proxy.refreshCustomPropertyGroups() - for g in sorted(obj.CustomPropertyGroups): - self.form.propertyGroup.addItem(g) - if grp: - self.form.propertyGroup.setCurrentText(grp) - - for t in sorted(PathPropertyBag.SupportedPropertyType): - self.form.propertyType.addItem(t) - if PathPropertyBag.SupportedPropertyType[t] == typ: - typ = t - if typ: - self.form.propertyType.setCurrentText(typ) - else: - self.form.propertyType.setCurrentText("String") - self.form.createAnother.setChecked(another) - - self.form.propertyGroup.currentTextChanged.connect(self.updateUI) - self.form.propertyGroup.currentIndexChanged.connect(self.updateUI) - self.form.propertyName.textChanged.connect(self.updateUI) - self.form.propertyType.currentIndexChanged.connect(self.updateUI) - self.form.propertyEnum.textChanged.connect(self.updateUI) - - def updateUI(self): - - typeSet = True - if self.propertyIsEnumeration(): - self.form.labelEnum.setEnabled(True) - self.form.propertyEnum.setEnabled(True) - typeSet = self.form.propertyEnum.text().strip() != "" - else: - self.form.labelEnum.setEnabled(False) - self.form.propertyEnum.setEnabled(False) - if self.form.propertyEnum.text().strip(): - self.form.propertyEnum.setText("") - - ok = self.form.buttonBox.button(QtGui.QDialogButtonBox.Ok) - - if not re.match("^[A-Za-z0-9_]*$", self.form.propertyName.text()): - typeSet = False - - if typeSet and self.propertyGroup(): - ok.setEnabled(True) - else: - ok.setEnabled(False) - - def propertyName(self): - return self.form.propertyName.text().strip() - - def propertyGroup(self): - return self.form.propertyGroup.currentText().strip() - - def propertyType(self): - return PathPropertyBag.SupportedPropertyType[ - self.form.propertyType.currentText() - ].strip() - - def propertyInfo(self): - return self.form.propertyInfo.toPlainText().strip() - - def createAnother(self): - return self.form.createAnother.isChecked() - - def propertyEnumerations(self): - return [s.strip() for s in self.form.propertyEnum.text().strip().split(",")] - - def propertyIsEnumeration(self): - return self.propertyType() == "App::PropertyEnumeration" - - def exec_(self, name): - if name: - # property exists - this is an edit operation - self.form.propertyName.setText(name) - if self.propertyIsEnumeration(): - self.form.propertyEnum.setText( - ",".join(self.obj.getEnumerationsOfProperty(name)) - ) - self.form.propertyInfo.setText(self.obj.getDocumentationOfProperty(name)) - - self.form.labelName.setEnabled(False) - self.form.propertyName.setEnabled(False) - self.form.labelType.setEnabled(False) - self.form.propertyType.setEnabled(False) - self.form.createAnother.setEnabled(False) - - else: - self.form.propertyName.setText("") - self.form.propertyInfo.setText("") - self.form.propertyEnum.setText("") - # self.form.propertyName.setFocus() - - self.updateUI() - - return self.form.exec_() - - -class TaskPanel(object): - ColumnName = 0 - # ColumnType = 1 - ColumnVal = 1 - # TableHeaders = ['Property', 'Type', 'Value'] - TableHeaders = ["Property", "Value"] - - def __init__(self, vobj): - self.obj = vobj.Object - self.props = sorted(self.obj.Proxy.getCustomProperties()) - self.form = FreeCADGui.PySideUic.loadUi(":panels/PropertyBag.ui") - - # initialized later - self.model = None - self.delegate = None - FreeCAD.ActiveDocument.openTransaction("Edit PropertyBag") - - def updateData(self, topLeft, bottomRight): - pass - - def _setupProperty(self, i, name): - typ = PathPropertyBag.getPropertyTypeName(self.obj.getTypeIdOfProperty(name)) - val = PathUtil.getPropertyValueString(self.obj, name) - info = self.obj.getDocumentationOfProperty(name) - - self.model.setData( - self.model.index(i, self.ColumnName), name, QtCore.Qt.EditRole - ) - # self.model.setData(self.model.index(i, self.ColumnType), typ, QtCore.Qt.EditRole) - self.model.setData( - self.model.index(i, self.ColumnVal), self.obj, Delegate.RoleObject - ) - self.model.setData( - self.model.index(i, self.ColumnVal), name, Delegate.RoleProperty - ) - self.model.setData( - self.model.index(i, self.ColumnVal), val, QtCore.Qt.DisplayRole - ) - - self.model.setData( - self.model.index(i, self.ColumnName), typ, QtCore.Qt.ToolTipRole - ) - # self.model.setData(self.model.index(i, self.ColumnType), info, QtCore.Qt.ToolTipRole) - self.model.setData( - self.model.index(i, self.ColumnVal), info, QtCore.Qt.ToolTipRole - ) - - self.model.item(i, self.ColumnName).setEditable(False) - # self.model.item(i, self.ColumnType).setEditable(False) - - def setupUi(self): - PathLog.track() - - self.delegate = Delegate(self.form) - self.model = QtGui.QStandardItemModel( - len(self.props), len(self.TableHeaders), self.form - ) - self.model.setHorizontalHeaderLabels(self.TableHeaders) - - for i, name in enumerate(self.props): - self._setupProperty(i, name) - - self.form.table.setModel(self.model) - self.form.table.setItemDelegateForColumn(self.ColumnVal, self.delegate) - self.form.table.resizeColumnsToContents() - - self.model.dataChanged.connect(self.updateData) - self.form.table.selectionModel().selectionChanged.connect(self.propertySelected) - self.form.add.clicked.connect(self.propertyAdd) - self.form.remove.clicked.connect(self.propertyRemove) - self.form.modify.clicked.connect(self.propertyModify) - self.form.table.doubleClicked.connect(self.propertyModifyIndex) - self.propertySelected([]) - - def accept(self): - FreeCAD.ActiveDocument.commitTransaction() - FreeCADGui.ActiveDocument.resetEdit() - FreeCADGui.Control.closeDialog() - FreeCAD.ActiveDocument.recompute() - - def reject(self): - FreeCAD.ActiveDocument.abortTransaction() - FreeCADGui.Control.closeDialog() - FreeCAD.ActiveDocument.recompute() - - def propertySelected(self, selection): - PathLog.track() - if selection: - self.form.modify.setEnabled(True) - self.form.remove.setEnabled(True) - else: - self.form.modify.setEnabled(False) - self.form.remove.setEnabled(False) - - def addCustomProperty(self, obj, dialog): - name = dialog.propertyName() - typ = dialog.propertyType() - grp = dialog.propertyGroup() - info = dialog.propertyInfo() - propname = self.obj.Proxy.addCustomProperty(typ, name, grp, info) - if dialog.propertyIsEnumeration(): - setattr(self.obj, name, dialog.propertyEnumerations()) - return (propname, info) - - def propertyAdd(self): - PathLog.track() - more = False - grp = None - typ = None - while True: - dialog = PropertyCreate(self.obj, grp, typ, more) - if dialog.exec_(None): - # if we block signals the view doesn't get updated, surprise, surprise - # self.model.blockSignals(True) - name, info = self.addCustomProperty(self.obj, dialog) - index = 0 - for i in range(self.model.rowCount()): - index = i - if ( - self.model.item(i, self.ColumnName).data(QtCore.Qt.EditRole) - > dialog.propertyName() - ): - break - self.model.insertRows(index, 1) - self._setupProperty(index, name) - self.form.table.selectionModel().setCurrentIndex( - self.model.index(index, 0), QtCore.QItemSelectionModel.Rows - ) - # self.model.blockSignals(False) - more = dialog.createAnother() - else: - more = False - if not more: - break - - def propertyModifyIndex(self, index): - PathLog.track(index.row(), index.column()) - row = index.row() - - obj = self.model.item(row, self.ColumnVal).data(Delegate.RoleObject) - nam = self.model.item(row, self.ColumnVal).data(Delegate.RoleProperty) - grp = obj.getGroupOfProperty(nam) - typ = obj.getTypeIdOfProperty(nam) - - dialog = PropertyCreate(self.obj, grp, typ, False) - if dialog.exec_(nam): - val = getattr(obj, nam) - obj.removeProperty(nam) - name, info = self.addCustomProperty(self.obj, dialog) - try: - setattr(obj, nam, val) - except Exception: - # this can happen if the old enumeration value doesn't exist anymore - pass - newVal = PathUtil.getPropertyValueString(obj, nam) - self.model.setData( - self.model.index(row, self.ColumnVal), newVal, QtCore.Qt.DisplayRole - ) - - # self.model.setData(self.model.index(row, self.ColumnType), info, QtCore.Qt.ToolTipRole) - self.model.setData( - self.model.index(row, self.ColumnVal), info, QtCore.Qt.ToolTipRole - ) - - def propertyModify(self): - PathLog.track() - rows = [] - for index in self.form.table.selectionModel().selectedIndexes(): - row = index.row() - if row in rows: - continue - rows.append(row) - - self.propertyModifyIndex(index) - - def propertyRemove(self): - PathLog.track() - # first find all rows which need to be removed - rows = [] - for index in self.form.table.selectionModel().selectedIndexes(): - if not index.row() in rows: - rows.append(index.row()) - - # then remove them in reverse order so the indexes of the remaining rows - # to delete are still valid - for row in reversed(sorted(rows)): - self.obj.removeProperty(self.model.item(row).data(QtCore.Qt.EditRole)) - self.model.removeRow(row) - - -def Create(name="PropertyBag"): - """Create(name = 'PropertyBag') ... creates a new setup sheet""" - FreeCAD.ActiveDocument.openTransaction("Create PropertyBag") - pcont = PathPropertyBag.Create(name) - PathIconViewProvider.Attach(pcont.ViewObject, name) - return pcont - - -PathIconViewProvider.RegisterViewProvider("PropertyBag", ViewProvider) - - -class PropertyBagCreateCommand(object): - """Command to create a property container object""" - - def __init__(self): - pass - - def GetResources(self): - return { - "MenuText": translate("Path_PropertyBag", "PropertyBag"), - "ToolTip": translate( - "Path_PropertyBag", - "Creates an object which can be used to store reference properties.", - ), - } - - def IsActive(self): - return not FreeCAD.ActiveDocument is None - - def Activated(self): - sel = FreeCADGui.Selection.getSelectionEx() - obj = Create() - body = None - if sel: - if "PartDesign::Body" == sel[0].Object.TypeId: - body = sel[0].Object - elif hasattr(sel[0].Object, "getParentGeoFeatureGroup"): - body = sel[0].Object.getParentGeoFeatureGroup() - if body: - obj.Label = "Attributes" - group = body.Group - group.append(obj) - body.Group = group - - -if FreeCAD.GuiUp: - FreeCADGui.addCommand("Path_PropertyBag", PropertyBagCreateCommand()) - -FreeCAD.Console.PrintLog("Loading PathPropertyBagGui ... done\n") +from Path.Base.Gui.PropertyBag import * diff --git a/src/Mod/Path/PathScripts/PathToolEdit.py b/src/Mod/Path/PathScripts/PathToolEdit.py deleted file mode 100644 index 8cb5b1afc9..0000000000 --- a/src/Mod/Path/PathScripts/PathToolEdit.py +++ /dev/null @@ -1,353 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2018 sliptonic * -# * * -# * 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 -import FreeCADGui -import Path -import PathScripts.PathLog as PathLog -import math - -from PySide import QtGui - -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) - - -class ToolEditorDefault: - """Generic Tool parameter editor for all Tools that don't have a customized edit function. - Let's the user enter the raw internal data. Not the best approach but this is the starting point.""" - - def __init__(self, editor): - self.editor = editor - self.form = editor.form - - def setupUI(self): - self.form.paramImage.hide() - self.form.paramGeneric.show() - - def updateUI(self): - self.form.toolDiameter.setText( - FreeCAD.Units.Quantity( - self.editor.tool.Diameter, FreeCAD.Units.Length - ).UserString - ) - self.form.toolFlatRadius.setText( - FreeCAD.Units.Quantity( - self.editor.tool.FlatRadius, FreeCAD.Units.Length - ).UserString - ) - self.form.toolCornerRadius.setText( - FreeCAD.Units.Quantity( - self.editor.tool.CornerRadius, FreeCAD.Units.Length - ).UserString - ) - self.form.toolCuttingEdgeHeight.setText( - FreeCAD.Units.Quantity( - self.editor.tool.CuttingEdgeHeight, FreeCAD.Units.Length - ).UserString - ) - self.form.toolCuttingEdgeAngle.setText( - FreeCAD.Units.Quantity( - self.editor.tool.CuttingEdgeAngle, FreeCAD.Units.Angle - ).UserString - ) - - def updateTool(self): - self.editor.tool.Diameter = FreeCAD.Units.parseQuantity( - self.form.toolDiameter.text() - ) - self.editor.tool.FlatRadius = FreeCAD.Units.parseQuantity( - self.form.toolFlatRadius.text() - ) - self.editor.tool.CornerRadius = FreeCAD.Units.parseQuantity( - self.form.toolCornerRadius.text() - ) - self.editor.tool.CuttingEdgeAngle = FreeCAD.Units.Quantity( - self.form.toolCuttingEdgeAngle.text() - ) - self.editor.tool.CuttingEdgeHeight = FreeCAD.Units.parseQuantity( - self.form.toolCuttingEdgeHeight.text() - ) - - -class ToolEditorImage(object): - """Base implementation for all customized Tool parameter editors. - While not required it is simplest to subclass specific editors.""" - - def __init__(self, editor, imageFile, hide="", disable=""): - self.editor = editor - self.form = editor.form - self.imagePath = "{}Mod/Path/Images/Tools/{}".format( - FreeCAD.getHomePath(), imageFile - ) - self.image = QtGui.QPixmap(self.imagePath) - self.hide = hide - self.disable = disable - - form = editor.form - self.widgets = { - "D": (form.label_D, form.value_D), - "d": (form.label_d, form.value_d), - "H": (form.label_H, form.value_H), - "a": (form.label_a, form.value_a), - "S": (form.label_S, form.value_S), - } - - def setupUI(self): - PathLog.track() - self.form.paramGeneric.hide() - self.form.paramImage.show() - - for key, widgets in self.widgets.items(): - hide = key in self.hide - disable = key in self.disable - for w in widgets: - w.setHidden(hide) - w.setDisabled(disable) - if not hide and not disable: - widgets[1].editingFinished.connect(self.editor.refresh) - - self.form.image.setPixmap(self.image) - - def updateUI(self): - PathLog.track() - self.form.value_D.setText(self.quantityDiameter(True).UserString) - self.form.value_d.setText(self.quantityFlatRadius(True).UserString) - self.form.value_a.setText(self.quantityCuttingEdgeAngle(True).UserString) - self.form.value_H.setText(self.quantityCuttingEdgeHeight(True).UserString) - - def updateTool(self): - PathLog.track() - toolDefault = Path.Tool() - if "D" in self.hide: - self.editor.tool.Diameter = toolDefault.Diameter - else: - self.editor.tool.Diameter = self.quantityDiameter(False) - - if "d" in self.hide: - self.editor.tool.FlatRadius = toolDefault.FlatRadius - else: - self.editor.tool.FlatRadius = self.quantityFlatRadius(False) - - if "a" in self.hide: - self.editor.tool.CuttingEdgeAngle = toolDefault.CuttingEdgeAngle - else: - self.editor.tool.CuttingEdgeAngle = self.quantityCuttingEdgeAngle(False) - - if "H" in self.hide: - self.editor.tool.CuttingEdgeHeight = toolDefault.CuttingEdgeHeight - else: - self.editor.tool.CuttingEdgeHeight = self.quantityCuttingEdgeHeight(False) - - self.editor.tool.CornerRadius = toolDefault.CornerRadius - - def quantityDiameter(self, propertyToDisplay): - if propertyToDisplay: - return FreeCAD.Units.Quantity( - self.editor.tool.Diameter, FreeCAD.Units.Length - ) - return FreeCAD.Units.parseQuantity(self.form.value_D.text()) - - def quantityFlatRadius(self, propertyToDisplay): - if propertyToDisplay: - return ( - FreeCAD.Units.Quantity( - self.editor.tool.FlatRadius, FreeCAD.Units.Length - ) - * 2 - ) - return FreeCAD.Units.parseQuantity(self.form.value_d.text()) / 2 - - def quantityCuttingEdgeAngle(self, propertyToDisplay): - if propertyToDisplay: - return FreeCAD.Units.Quantity( - self.editor.tool.CuttingEdgeAngle, FreeCAD.Units.Angle - ) - return FreeCAD.Units.parseQuantity(self.form.value_a.text()) - - def quantityCuttingEdgeHeight(self, propertyToDisplay): - if propertyToDisplay: - return FreeCAD.Units.Quantity( - self.editor.tool.CuttingEdgeHeight, FreeCAD.Units.Length - ) - return FreeCAD.Units.parseQuantity(self.form.value_H.text()) - - -class ToolEditorEndmill(ToolEditorImage): - """Tool parameter editor for endmills.""" - - def __init__(self, editor): - super(ToolEditorEndmill, self).__init__(editor, "endmill.svg", "da", "S") - - -class ToolEditorReamer(ToolEditorImage): - """Tool parameter editor for reamers.""" - - def __init__(self, editor): - super(ToolEditorReamer, self).__init__(editor, "reamer.svg", "da", "S") - - -class ToolEditorDrill(ToolEditorImage): - """Tool parameter editor for drills.""" - - def __init__(self, editor): - super(ToolEditorDrill, self).__init__(editor, "drill.svg", "dS", "") - - def quantityCuttingEdgeAngle(self, propertyToDisplay): - if propertyToDisplay: - return FreeCAD.Units.Quantity( - self.editor.tool.CuttingEdgeAngle, FreeCAD.Units.Angle - ) - return FreeCAD.Units.parseQuantity(self.form.value_a.text()) - - -class ToolEditorEngrave(ToolEditorImage): - """Tool parameter editor for v-bits.""" - - def __init__(self, editor): - super(ToolEditorEngrave, self).__init__(editor, "v-bit.svg", "", "dS") - - def quantityCuttingEdgeHeight(self, propertyToDisplay): - PathLog.track() - dr = (self.quantityDiameter(False) - self.quantityFlatRadius(False)) / 2 - da = self.quantityCuttingEdgeAngle(False).Value - return dr / math.tan(math.radians(da) / 2) - - -class ToolEditor: - """UI and controller for editing a Tool. - The controller embeds the UI to the parentWidget which has to have a layout attached to it. - The editor maintains two Tools, self.tool and self.Tool. The former is the one being edited - and always reflects the current state. self.Tool on the other hand is the "official" Tool - which should be used externally. The state is transferred between the two with accept and - reject. - - The editor uses instances of ToolEditorDefault and ToolEditorImage to deal with the changes - of the actual parameters. For any ToolType not mapped in ToolTypeImage the editor uses - an instance of ToolEditorDefault. - """ - - ToolTypeImage = { - "EndMill": ToolEditorEndmill, - "Drill": ToolEditorDrill, - "Engraver": ToolEditorEngrave, - "Reamer": ToolEditorReamer, - } - - def __init__(self, tool, parentWidget, parent=None): - self.Parent = parent - self.Tool = tool - self.tool = tool.copy() - self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolEditor.ui") - - self.form.setParent(parentWidget) - parentWidget.layout().addWidget(self.form) - - for tooltype in Path.Tool.getToolTypes(tool): - self.form.toolType.addItem(tooltype) - for material in Path.Tool.getToolMaterials(tool): - self.form.toolMaterial.addItem(material) - - self.setupToolType(self.tool.ToolType) - - def accept(self): - self.refresh() - self.Tool = self.tool - - def reject(self): - self.tool = self.Tool - - def getType(self, tooltype): - "gets a combobox index number for a given type or vice versa" - toolslist = Path.Tool.getToolTypes(Path.Tool()) - if isinstance(tooltype, str): - if tooltype in toolslist: - return toolslist.index(tooltype) - else: - return 0 - return toolslist[tooltype] - - def getMaterial(self, material): - "gets a combobox index number for a given material or vice versa" - matslist = Path.Tool.getToolMaterials(Path.Tool()) - if isinstance(material, str): - if material in matslist: - return matslist.index(material) - else: - return 0 - return matslist[material] - - def updateUI(self): - PathLog.track() - self.form.toolName.setText(self.tool.Name) - self.form.toolType.setCurrentIndex(self.getType(self.tool.ToolType)) - self.form.toolMaterial.setCurrentIndex(self.getMaterial(self.tool.Material)) - self.form.toolLengthOffset.setText( - FreeCAD.Units.Quantity( - self.tool.LengthOffset, FreeCAD.Units.Length - ).UserString - ) - - self.editor.updateUI() - - def updateToolType(self): - PathLog.track() - self.form.blockSignals(True) - self.tool.ToolType = self.getType(self.form.toolType.currentIndex()) - self.setupToolType(self.tool.ToolType) - self.updateUI() - self.form.blockSignals(False) - - def setupToolType(self, tt): - PathLog.track() - print("Tool type: %s" % (tt)) - if "Undefined" == tt: - tt = Path.Tool.getToolTypes(Path.Tool())[0] - if tt in self.ToolTypeImage: - self.editor = self.ToolTypeImage[tt](self) - else: - PathLog.debug("weak supported ToolType = %s" % (tt)) - self.editor = ToolEditorDefault(self) - self.editor.setupUI() - - def updateTool(self): - PathLog.track() - self.tool.Name = str(self.form.toolName.text()) - self.tool.Material = self.getMaterial(self.form.toolMaterial.currentIndex()) - self.tool.LengthOffset = FreeCAD.Units.parseQuantity( - self.form.toolLengthOffset.text() - ) - self.editor.updateTool() - - def refresh(self): - PathLog.track() - self.form.blockSignals(True) - self.updateTool() - self.updateUI() - self.form.blockSignals(False) - - def setupUI(self): - PathLog.track() - self.updateUI() - - self.form.toolName.editingFinished.connect(self.refresh) - self.form.toolType.currentIndexChanged.connect(self.updateToolType) diff --git a/src/Mod/Path/PathScripts/PathToolLibraryEditor.py b/src/Mod/Path/PathScripts/PathToolLibraryEditor.py deleted file mode 100644 index 77b1157829..0000000000 --- a/src/Mod/Path/PathScripts/PathToolLibraryEditor.py +++ /dev/null @@ -1,515 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2014 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** - -from __future__ import print_function -from PySide import QtCore, QtGui -from PySide.QtCore import QT_TRANSLATE_NOOP -import FreeCAD -import FreeCADGui -import Path -import PathScripts -import PathScripts.PathLog as PathLog -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathToolBitLibraryCmd as PathToolBitLibraryCmd -import PathScripts.PathToolEdit as PathToolEdit -import PathScripts.PathToolLibraryManager as ToolLibraryManager -import PathScripts.PathUtils as PathUtils - - -if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) -else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) - -translate = FreeCAD.Qt.translate - - -class EditorPanel: - def __init__(self, job, cb): - self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolLibraryEditor.ui") - self.TLM = ToolLibraryManager.ToolLibraryManager() - listname = self.TLM.getCurrentTableName() - - if listname: - self.loadToolTables() - - self.job = job - self.cb = cb - - def toolEditor(self, tool): - dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgToolEdit.ui") - editor = PathToolEdit.ToolEditor(tool, dialog.toolEditor, dialog) - editor.setupUI() - return editor - - def accept(self): - pass - - def reject(self): - FreeCADGui.Control.closeDialog() - FreeCAD.ActiveDocument.recompute() - - def getFields(self): - pass - - def setFields(self): - pass - - def open(self): - pass - - def getType(self, tooltype): - "gets a combobox index number for a given type or vice versa" - toolslist = Path.Tool.getToolTypes(Path.Tool()) - if isinstance(tooltype, str): - if tooltype in toolslist: - return toolslist.index(tooltype) - else: - return 0 - else: - return toolslist[tooltype] - - def getMaterial(self, material): - """gets a combobox index number for a given material or vice versa""" - matslist = Path.Tool.getToolMaterials(Path.Tool()) - if isinstance(material, str): - if material in matslist: - return matslist.index(material) - else: - return 0 - else: - return matslist[material] - - def addTool(self): - """adds new tool to the current tool table""" - tool = Path.Tool() - editor = self.toolEditor(tool) - - r = editor.Parent.exec_() - if r: - editor.accept() - listname = self.TLM.getCurrentTableName() - self.TLM.addnew(listname, editor.Tool) - self.loadTable(listname) - - def delete(self): - """deletes the selected tool""" - listname = self.TLM.getCurrentTableName() - model = self.form.ToolsList.model() - for i in range(model.rowCount()): - item = model.item(i, 0) - if item.checkState(): - t = model.index(i, 1) - self.TLM.delete(int(t.data()), listname) - self.loadTable(listname) - self.toolSelectionChanged() - - def editTool(self, currItem): - """load the tool edit dialog""" - if not currItem: - currItem = self.form.ToolsList.selectedIndexes()[1] - - row = currItem.row() - value = currItem.sibling(row, 1).data() - listname = self.TLM.getCurrentTableName() - toolnum = int(value) - tool = self.TLM.getTool(listname, toolnum) - editor = self.toolEditor(tool) - - r = editor.Parent.exec_() - if r: - editor.accept() - if self.TLM.updateTool(listname, toolnum, editor.Tool) is True: - self.loadTable(listname) - - def moveUp(self): - """moves a tool to a lower number, if possible""" - item = self.form.ToolsList.selectedIndexes()[1].data() - if item: - number = int(item) - listname = self.TLM.getCurrentTableName() - success, newNum = self.TLM.moveup(number, listname) - if success: - self.loadTable(listname) - self.updateSelection(newNum) - - def moveDown(self): - """moves a tool to a higher number, if possible""" - item = self.form.ToolsList.selectedIndexes()[1].data() - if item: - number = int(item) - listname = self.TLM.getCurrentTableName() - success, newNum = self.TLM.movedown(number, listname) - if success: - self.loadTable(listname) - self.updateSelection(newNum) - - def duplicate(self): - """duplicated the selected tool in the current tool table""" - item = self.form.ToolsList.selectedIndexes()[1].data() - if item: - number = int(item) - listname = self.TLM.getCurrentTableName() - success, newNum = self.TLM.duplicate(number, listname) - if success: - self.loadTable(listname) - self.updateSelection(newNum) - - def updateSelection(self, number): - """update the tool list selection to track moves""" - model = self.form.ToolsList.model() - for i in range(model.rowCount()): - if int(model.index(i, 1).data()) == number: - self.form.ToolsList.selectRow(i) - self.form.ToolsList.model().item(i, 0).setCheckState(QtCore.Qt.Checked) - return - - def importFile(self): - """imports a tooltable from a file""" - filename = QtGui.QFileDialog.getOpenFileName( - self.form, - translate("Path_ToolTable", "Open tooltable"), - None, - "{};;{};;{}".format( - self.TLM.TooltableTypeJSON, - self.TLM.TooltableTypeXML, - self.TLM.TooltableTypeHeekscad, - ), - ) - if filename[0]: - listname = self.TLM.getNextToolTableName() - if self.TLM.read(filename, listname): - self.loadToolTables() - - def exportFile(self): - """export a tooltable to a file""" - filename = QtGui.QFileDialog.getSaveFileName( - self.form, - translate("Path_ToolTable", "Save tooltable"), - None, - "{};;{};;{}".format( - self.TLM.TooltableTypeJSON, - self.TLM.TooltableTypeXML, - self.TLM.TooltableTypeLinuxCNC, - ), - ) - if filename[0]: - listname = self.TLM.getCurrentTableName() - self.TLM.write(filename, listname) - - def toolSelectionChanged(self, index=None): - """updates the ui when tools are selected""" - if index: - self.form.ToolsList.selectRow(index.row()) - - self.form.btnCopyTools.setEnabled(False) - self.form.ButtonDelete.setEnabled(False) - self.form.ButtonUp.setEnabled(False) - self.form.ButtonDown.setEnabled(False) - self.form.ButtonEdit.setEnabled(False) - self.form.ButtonDuplicate.setEnabled(False) - - model = self.form.ToolsList.model() - checkCount = 0 - checkList = [] - for i in range(model.rowCount()): - item = model.item(i, 0) - if item.checkState(): - checkCount += 1 - checkList.append(i) - self.form.btnCopyTools.setEnabled(True) - - # only allow moving or deleting a single tool at a time. - if checkCount == 1: - # make sure the row is highlighted when the check box gets ticked - self.form.ToolsList.selectRow(checkList[0]) - self.form.ButtonDelete.setEnabled(True) - self.form.ButtonUp.setEnabled(True) - self.form.ButtonDown.setEnabled(True) - self.form.ButtonEdit.setEnabled(True) - self.form.ButtonDuplicate.setEnabled(True) - - if len(PathUtils.GetJobs()) == 0: - self.form.btnCopyTools.setEnabled(False) - - def copyTools(self): - """copy selected tool""" - tools = [] - model = self.form.ToolsList.model() - for i in range(model.rowCount()): - item = model.item(i, 0) - if item.checkState(): - item = model.index(i, 1) - tools.append(item.data()) - if len(tools) == 0: - return - - targets = self.TLM.getJobList() - currList = self.TLM.getCurrentTableName() - - for target in targets: - if target == currList: - targets.remove(target) - - if len(targets) == 0: - FreeCAD.Console.PrintWarning("No Path Jobs in current document") - return - elif len(targets) == 1: - targetlist = targets[0] - else: - form = FreeCADGui.PySideUic.loadUi(":/panels/DlgToolCopy.ui") - form.cboTarget.addItems(targets) - r = form.exec_() - if r is False: - return None - else: - targetlist = form.cboTarget.currentText() - - for toolnum in tools: - tool = self.TLM.getTool(currList, int(toolnum)) - PathLog.debug("tool: {}, toolnum: {}".format(tool, toolnum)) - if self.job: - label = "T{}: {}".format(toolnum, tool.Name) - tc = PathScripts.PathToolController.Create( - label, tool=tool, toolNumber=int(toolnum) - ) - self.job.Proxy.addToolController(tc) - else: - for job in FreeCAD.ActiveDocument.findObjects("Path::Feature"): - if ( - isinstance(job.Proxy, PathScripts.PathJob.ObjectJob) - and job.Label == targetlist - ): - label = "T{}: {}".format(toolnum, tool.Name) - tc = PathScripts.PathToolController.Create( - label, tool=tool, toolNumber=int(toolnum) - ) - job.Proxy.addToolController(tc) - if self.cb: - self.cb() - FreeCAD.ActiveDocument.recompute() - - def tableSelected(self, index): - """loads the tools for the selected tool table""" - name = self.form.TableList.itemWidget( - self.form.TableList.itemFromIndex(index) - ).getTableName() - self.loadTable(name) - - def loadTable(self, name): - """loads the tools for the selected tool table""" - tooldata = self.TLM.getTools(name) - if tooldata: - self.form.ToolsList.setModel(tooldata) - self.form.ToolsList.resizeColumnsToContents() - self.form.ToolsList.horizontalHeader().setResizeMode( - self.form.ToolsList.model().columnCount() - 1, QtGui.QHeaderView.Stretch - ) - self.setCurrentToolTableByName(name) - - def addNewToolTable(self): - """adds new tool to selected tool table""" - name = self.TLM.addNewToolTable() - self.loadToolTables() - self.loadTable(name) - - def loadToolTables(self): - """Load list of available tool tables""" - self.form.TableList.clear() - model = self.form.ToolsList.model() - if model: - model.clear() - if len(self.TLM.getToolTables()) > 0: - for table in self.TLM.getToolTables(): - listWidgetItem = QtGui.QListWidgetItem() - listItem = ToolTableListWidgetItem(self.TLM) - listItem.setTableName(table.Name) - listItem.setIcon(QtGui.QPixmap(":/icons/Path_ToolTable.svg")) - listItem.toolMoved.connect(self.reloadReset) - listWidgetItem.setSizeHint(QtCore.QSize(0, 40)) - self.form.TableList.addItem(listWidgetItem) - self.form.TableList.setItemWidget(listWidgetItem, listItem) - # Load the first tooltable - self.loadTable(self.TLM.getCurrentTableName()) - - def reloadReset(self): - """reloads the current tooltable""" - name = self.TLM.getCurrentTableName() - self.loadTable(name) - - def setCurrentToolTableByName(self, name): - """get the current tool table""" - item = self.getToolTableByName(name) - if item: - self.form.TableList.setCurrentItem(item) - - def getToolTableByName(self, name): - """returns the listWidgetItem for the selected name""" - for i in range(self.form.TableList.count()): - tableName = self.form.TableList.itemWidget( - self.form.TableList.item(i) - ).getTableName() - if tableName == name: - return self.form.TableList.item(i) - return False - - def removeToolTable(self): - """delete the selected tool table""" - self.TLM.deleteToolTable() - self.loadToolTables() - - def renameTable(self): - """provides dialog for new tablename and renames the selected tool table""" - name = self.TLM.getCurrentTableName() - newName, ok = QtGui.QInputDialog.getText( - None, - translate("Path_ToolTable", "Rename Tooltable"), - translate("Path_ToolTable", "Enter Name:"), - QtGui.QLineEdit.Normal, - name, - ) - if ok and newName: - index = self.form.TableList.indexFromItem( - self.getToolTableByName(name) - ).row() - reloadTables = self.TLM.renameToolTable(newName, index) - if reloadTables: - self.loadToolTables() - self.loadTable(newName) - - def getStandardButtons(self): - return int(QtGui.QDialogButtonBox.Ok) - - def setupUi(self): - # Connect Signals and Slots - self.form.ButtonNewTool.clicked.connect(self.addTool) - self.form.ButtonImport.clicked.connect(self.importFile) - self.form.ButtonExport.clicked.connect(self.exportFile) - self.form.ButtonDown.clicked.connect(self.moveDown) - self.form.ButtonUp.clicked.connect(self.moveUp) - self.form.ButtonDelete.clicked.connect(self.delete) - self.form.ButtonEdit.clicked.connect(self.editTool) - self.form.ButtonDuplicate.clicked.connect(self.duplicate) - self.form.btnCopyTools.clicked.connect(self.copyTools) - - self.form.ToolsList.doubleClicked.connect(self.editTool) - self.form.ToolsList.clicked.connect(self.toolSelectionChanged) - - self.form.TableList.clicked.connect(self.tableSelected) - self.form.TableList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - self.form.TableList.itemChanged.connect(self.renameTable) - - self.form.ButtonAddToolTable.clicked.connect(self.addNewToolTable) - self.form.ButtonAddToolTable.setToolTip( - translate("Path_ToolTable", "Add New Tool Table") - ) - self.form.ButtonRemoveToolTable.clicked.connect(self.removeToolTable) - self.form.ButtonRemoveToolTable.setToolTip( - translate("Path_ToolTable", "Delete Selected Tool Table") - ) - self.form.ButtonRenameToolTable.clicked.connect(self.renameTable) - self.form.ButtonRenameToolTable.setToolTip( - translate("Path_ToolTable", "Rename Selected Tool Table") - ) - - self.setFields() - - -class ToolTableListWidgetItem(QtGui.QWidget): - - toolMoved = QtCore.Signal() - - def __init__(self, TLM): - super(ToolTableListWidgetItem, self).__init__() - - self.tlm = TLM - self.setAcceptDrops(True) - - self.mainLayout = QtGui.QHBoxLayout() - self.iconQLabel = QtGui.QLabel() - self.tableNameLabel = QtGui.QLabel() - self.mainLayout.addWidget(self.iconQLabel, 0) - self.mainLayout.addWidget(self.tableNameLabel, 1) - self.setLayout(self.mainLayout) - - def setTableName(self, text): - self.tableNameLabel.setText(text) - - def getTableName(self): - return self.tableNameLabel.text() - - def setIcon(self, icon): - icon = icon.scaled(24, 24) - self.iconQLabel.setPixmap(icon) - - def dragEnterEvent(self, e): - currentToolTable = self.tlm.getCurrentTableName() - thisToolTable = self.getTableName() - - if not currentToolTable == thisToolTable: - e.accept() - else: - e.ignore() - - def dropEvent(self, e): - selectedTools = e.source().selectedIndexes() - if selectedTools: - toolData = selectedTools[1].data() - - if toolData: - self.tlm.moveToTable(int(toolData), self.getTableName()) - self.toolMoved.emit() - - -class CommandToolLibraryEdit: - def __init__(self): - pass - - def edit(self, job=None, cb=None): - if PathPreferences.toolsUseLegacyTools(): - editor = EditorPanel(job, cb) - editor.setupUi() - editor.form.exec_() - else: - if PathToolBitLibraryCmd.CommandToolBitLibraryLoad.Execute(job): - if cb: - cb() - - def GetResources(self): - return { - "Pixmap": "Path_ToolTable", - "MenuText": QT_TRANSLATE_NOOP("Path_ToolTable", "Tool Manager"), - "Accel": "P, T", - "ToolTip": QT_TRANSLATE_NOOP("Path_ToolTable", "Tool Manager"), - } - - def IsActive(self): - return not FreeCAD.ActiveDocument is None - - def Activated(self): - self.edit() - - -if FreeCAD.GuiUp: - # register the FreeCAD command - FreeCADGui.addCommand("Path_ToolLibraryEdit", CommandToolLibraryEdit()) diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py deleted file mode 100644 index 36c298c821..0000000000 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ /dev/null @@ -1,562 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2014 sliptonic * -# * * -# * 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 * -# * * -# *************************************************************************** - -from __future__ import print_function - -import FreeCAD -import Path -import PathScripts -import PathScripts.PathLog as PathLog -import PathScripts.PathUtil as PathUtil -import json -import os -import xml.sax -from PySide import QtGui - -if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) -else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) - -translate = FreeCAD.Qt.translate - -# Tooltable XML readers -class FreeCADTooltableHandler(xml.sax.ContentHandler): - # http://www.tutorialspoint.com/python/python_xml_processing.htm - - def __init__(self): - xml.sax.ContentHandler.__init__(self) - self.tooltable = None - self.tool = None - self.number = None - - # Call when an element is found - def startElement(self, name, attrs): - if name == "Tooltable": - self.tooltable = Path.Tooltable() - elif name == "Toolslot": - self.number = int(attrs["number"]) - elif name == "Tool": - self.tool = Path.Tool() - self.tool.Name = str(attrs["name"]) - self.tool.ToolType = str(attrs["type"]) - self.tool.Material = str(attrs["mat"]) - # for some reason without the following line I get an error - # print attrs["diameter"] - self.tool.Diameter = float(attrs["diameter"]) - self.tool.LengthOffset = float(attrs["length"]) - self.tool.FlatRadius = float(attrs["flat"]) - self.tool.CornerRadius = float(attrs["corner"]) - self.tool.CuttingEdgeAngle = float(attrs["angle"]) - self.tool.CuttingEdgeHeight = float(attrs["height"]) - - # Call when an elements ends - def endElement(self, name): - if name == "Toolslot": - if self.tooltable and self.tool and self.number: - self.tooltable.setTool(self.number, self.tool) - self.number = None - self.tool = None - - -class HeeksTooltableHandler(xml.sax.ContentHandler): - def __init__(self): - xml.sax.ContentHandler.__init__(self) - self.tooltable = Path.Tooltable() - self.tool = None - self.number = None - - # Call when an element is found - def startElement(self, name, attrs): - if name == "Tool": - self.tool = Path.Tool() - self.number = int(attrs["tool_number"]) - self.tool.Name = str(attrs["title"]) - elif name == "params": - t = str(attrs["type"]) - if t == "drill": - self.tool.ToolType = "Drill" - elif t == "center_drill_bit": - self.tool.ToolType = "CenterDrill" - elif t == "end_mill": - self.tool.ToolType = "EndMill" - elif t == "slot_cutter": - self.tool.ToolType = "SlotCutter" - elif t == "ball_end_mill": - self.tool.ToolType = "BallEndMill" - elif t == "chamfer": - self.tool.ToolType = "Chamfer" - elif t == "engraving_bit": - self.tool.ToolType = "Engraver" - m = str(attrs["material"]) - if m == "0": - self.tool.Material = "HighSpeedSteel" - elif m == "1": - self.tool.Material = "Carbide" - # for some reason without the following line I get an error - # print attrs["diameter"] - self.tool.Diameter = float(attrs["diameter"]) - self.tool.LengthOffset = float(attrs["tool_length_offset"]) - self.tool.FlatRadius = float(attrs["flat_radius"]) - self.tool.CornerRadius = float(attrs["corner_radius"]) - self.tool.CuttingEdgeAngle = float(attrs["cutting_edge_angle"]) - self.tool.CuttingEdgeHeight = float(attrs["cutting_edge_height"]) - - # Call when an elements ends - def endElement(self, name): - if name == "Tool": - if self.tooltable and self.tool and self.number: - self.tooltable.setTool(self.number, self.tool) - self.number = None - self.tool = None - - -class ToolLibraryManager: - """ - The Tool Library is a list of individual tool tables. Each - Tool Table can contain n tools. The tool library will be persisted to user - preferences and all or part of the library can be exported to other formats - """ - - TooltableTypeJSON = translate("PathToolLibraryManager", "Tooltable JSON (*.json)") - TooltableTypeXML = translate("PathToolLibraryManager", "Tooltable XML (*.xml)") - TooltableTypeHeekscad = translate( - "PathToolLibraryManager", "HeeksCAD tooltable (*.tooltable)" - ) - TooltableTypeLinuxCNC = translate( - "PathToolLibraryManager", "LinuxCNC tooltable (*.tbl)" - ) - - PreferenceMainLibraryXML = "ToolLibrary" - PreferenceMainLibraryJSON = "ToolLibrary-Main" - - def __init__(self): - self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") - self.toolTables = [] - self.currentTableName = None - self.loadToolTables() - - def getToolTables(self): - """Return tool table list""" - return self.toolTables - - def getCurrentTableName(self): - """return the name of the currently loaded tool table""" - return self.currentTableName - - def getCurrentTable(self): - """returns an object of the current tool table""" - return self.getTableFromName(self.currentTableName) - - def getTableFromName(self, name): - """get the tool table object from the name""" - for table in self.toolTables: - if table.Name == name: - return table - - def getNextToolTableName(self, tableName="Tool Table"): - """get a unique name for a new tool table""" - iter = 1 - tempName = tableName[-2:] - - if tempName[0] == "-" and tempName[-1].isdigit(): - tableName = tableName[:-2] - - while any( - table.Name == tableName + "-" + str(iter) for table in self.toolTables - ): - iter += 1 - - return tableName + "-" + str(iter) - - def addNewToolTable(self): - """creates a new tool table""" - tt = Path.Tooltable() - tt.Version = 1 - name = self.getNextToolTableName() - tt.Name = name - self.toolTables.append(tt) - self.saveMainLibrary() - return name - - def deleteToolTable(self): - """deletes the selected tool table""" - if len(self.toolTables): - index = next( - ( - index - for (index, d) in enumerate(self.toolTables) - if d.Name == self.currentTableName - ), - None, - ) - self.toolTables.pop(index) - self.saveMainLibrary() - - def renameToolTable(self, newName, index): - """renames a tool table with the new name""" - currentTableName = self.toolTables[index].Name - if newName == currentTableName: - PathLog.error(translate("PathToolLibraryManager", "Tool Table Same Name")) - return False - if newName in self.toolTables: - PathLog.error(translate("PathToolLibraryManager", "Tool Table Name Exists")) - return False - tt = self.getTableFromName(currentTableName) - if tt: - tt.Name = newName - self.saveMainLibrary() - return True - - def templateAttrs(self): - """gets the tool table arributes""" - toolTables = [] - for tt in self.toolTables: - tableData = {} - tableData["Version"] = 1 - tableData["TableName"] = tt.Name - - toolData = {} - for tool in tt.Tools: - toolData[tool] = tt.Tools[tool].templateAttrs() - - tableData["Tools"] = toolData - toolTables.append(tableData) - - return toolTables - - def tooltableFromAttrs(self, stringattrs): - if stringattrs.get("Version") and 1 == int(stringattrs["Version"]): - - tt = Path.Tooltable() - tt.Version = 1 - tt.Name = self.getNextToolTableName() - - if stringattrs.get("Version"): - tt.Version = stringattrs.get("Version") - - if stringattrs.get("TableName"): - tt.Name = stringattrs.get("TableName") - if any(table.Name == tt.Name for table in self.toolTables): - tt.Name = self.getNextToolTableName(tt.Name) - - for key, attrs in PathUtil.keyValueIter(stringattrs["Tools"]): - tool = Path.Tool() - tool.Name = str(attrs["name"]) - tool.ToolType = str(attrs["tooltype"]) - tool.Material = str(attrs["material"]) - tool.Diameter = float(attrs["diameter"]) - tool.LengthOffset = float(attrs["lengthOffset"]) - tool.FlatRadius = float(attrs["flatRadius"]) - tool.CornerRadius = float(attrs["cornerRadius"]) - tool.CuttingEdgeAngle = float(attrs["cuttingEdgeAngle"]) - tool.CuttingEdgeHeight = float(attrs["cuttingEdgeHeight"]) - tt.setTool(int(key), tool) - - return tt - else: - PathLog.error( - translate( - "PathToolLibraryManager", - "Unsupported Path tooltable template version %s", - ) - % stringattrs.get("Version") - ) - return None - - def loadToolTables(self): - """loads the tool tables from the stored data""" - self.toolTables = [] - self.currentTableName = "" - - def addTable(tt): - if tt: - self.toolTables.append(tt) - else: - PathLog.error( - translate("PathToolLibraryManager", "Unsupported Path tooltable") - ) - - prefString = self.prefs.GetString(self.PreferenceMainLibraryJSON, "") - - if not prefString: - return - - prefsData = json.loads(prefString) - - if isinstance(prefsData, dict): - tt = self.tooltableFromAttrs(prefsData) - addTable(tt) - - if isinstance(prefsData, list): - for table in prefsData: - tt = self.tooltableFromAttrs(table) - addTable(tt) - - if len(self.toolTables): - self.currentTableName = self.toolTables[0].Name - - def saveMainLibrary(self): - """Persists the permanent library to FreeCAD user preferences""" - tmpstring = json.dumps(self.templateAttrs()) - self.prefs.SetString(self.PreferenceMainLibraryJSON, tmpstring) - self.loadToolTables() - return True - - def getJobList(self): - """Builds the list of all Tool Table lists""" - tablelist = [] - - for o in FreeCAD.ActiveDocument.Objects: - if hasattr(o, "Proxy"): - if isinstance(o.Proxy, PathScripts.PathJob.ObjectJob): - tablelist.append(o.Label) - - return tablelist - - def getTool(self, listname, toolnum): - """gets the tool object""" - tt = self.getTableFromName(listname) - return tt.getTool(toolnum) - - def getTools(self, tablename): - """returns the tool data for a given table""" - tooldata = [] - tableExists = any(table.Name == tablename for table in self.toolTables) - if tableExists: - self.currentTableName = tablename - else: - return None - - tt = self.getTableFromName(tablename) - headers = ["", "Tool Num.", "Name", "Tool Type", "Diameter"] - model = QtGui.QStandardItemModel() - model.setHorizontalHeaderLabels(headers) - - def unitconv(ivalue): - val = FreeCAD.Units.Quantity(ivalue, FreeCAD.Units.Length) - displayed_val = ( - val.UserString - ) # just the displayed value-not the internal one - return displayed_val - - if tt: - if len(tt.Tools) == 0: - tooldata.append([]) - for number, t in PathUtil.keyValueIter(tt.Tools): - - itemcheck = QtGui.QStandardItem() - itemcheck.setCheckable(True) - itemNumber = QtGui.QStandardItem(str(number)) - itemName = QtGui.QStandardItem(t.Name) - itemToolType = QtGui.QStandardItem(t.ToolType) - itemDiameter = QtGui.QStandardItem(unitconv(t.Diameter)) - - row = [itemcheck, itemNumber, itemName, itemToolType, itemDiameter] - model.appendRow(row) - - return model - - # methods for importing and exporting - def read(self, filename, listname): - "imports a tooltable from a file" - - importedTables = [] - - try: - fileExtension = os.path.splitext(filename[0])[1].lower() - xmlHandler = None - if fileExtension == ".tooltable": - xmlHandler = HeeksTooltableHandler() - if fileExtension == ".xml": - xmlHandler = FreeCADTooltableHandler() - - if xmlHandler: - parser = xml.sax.make_parser() - parser.setFeature(xml.sax.handler.feature_namespaces, 0) - parser.setContentHandler(xmlHandler) - parser.parse(PathUtil.toUnicode(filename[0])) - if not xmlHandler.tooltable: - return None - - ht = xmlHandler.tooltable - else: - with open(PathUtil.toUnicode(filename[0]), "rb") as fp: - tableData = json.load(fp) - - if isinstance(tableData, dict): - ht = self.tooltableFromAttrs(tableData) - if ht: - importedTables.append(ht) - - if isinstance(tableData, list): - for table in tableData: - ht = self.tooltableFromAttrs(table) - if ht: - importedTables.append(ht) - - if importedTables: - for tt in importedTables: - self.toolTables.append(tt) - - self.saveMainLibrary() - return True - else: - return False - - except Exception as e: - print("could not parse file", e) - - def write(self, filename, listname): - "exports the tooltable to a file" - tt = self.getTableFromName(listname) - if tt: - try: - - def openFileWithExtension(name, ext): - fext = os.path.splitext(name)[1].lower() - if fext != ext: - name = "{}{}".format(name, ext) - return (open(PathUtil.toUnicode(name), "w"), name) - - if filename[1] == self.TooltableTypeXML: - fp, fname = openFileWithExtension(filename[0], ".xml") - fp.write('\n') - fp.write(tt.Content) - elif filename[1] == self.TooltableTypeLinuxCNC: - fp, fname = openFileWithExtension(filename[0], ".tbl") - for key in tt.Tools: - t = tt.Tools[key] - fp.write( - "T{0} P{0} Y{1} Z{2} A{3} B{4} C{5} U{6} V{7} W{8} D{9} I{10} J{11} Q{12} ;{13}\n".format( - key, - 0, - t.LengthOffset, - 0, - 0, - 0, - 0, - 0, - 0, - t.Diameter, - 0, - 0, - 0, - t.Name, - ) - ) - else: - fp, fname = openFileWithExtension(filename[0], ".json") - json.dump(self.templateAttrs(), fp, sort_keys=True, indent=2) - - fp.close() - print("Written ", PathUtil.toUnicode(fname)) - - except Exception as e: - print("Could not write file:", e) - - def addnew(self, listname, tool, position=None): - "adds a new tool at the end of the table" - tt = self.getTableFromName(listname) - if not tt: - tt = Path.Tooltable() - if position is None: - tt.addTools(tool) - newID = list(tt.Tools)[-1] - else: - tt.setTool(position, tool) - newID = position - - if listname == self.getCurrentTableName(): - self.saveMainLibrary() - return newID - - def updateTool(self, listname, toolnum, tool): - """updates tool data""" - tt = self.getTableFromName(listname) - tt.deleteTool(toolnum) - tt.setTool(toolnum, tool) - if listname == self.getCurrentTableName(): - return self.saveMainLibrary() - return True - - def moveup(self, number, listname): - "moves a tool to a lower number, if possible" - target = number - 1 - if number < 2: - return False, target - target = number - 1 - tt = self.getTableFromName(listname) - t1 = tt.getTool(number).copy() - tt.deleteTool(number) - if target in tt.Tools.keys(): - t2 = tt.getTool(target).copy() - tt.deleteTool(target) - tt.setTool(number, t2) - tt.setTool(target, t1) - if listname == self.getCurrentTableName(): - self.saveMainLibrary() - return True, target - - def movedown(self, number, listname): - "moves a tool to a higher number, if possible" - tt = self.getTableFromName(listname) - target = number + 1 - t1 = tt.getTool(number).copy() - tt.deleteTool(number) - if target in tt.Tools.keys(): - t2 = tt.getTool(target).copy() - tt.deleteTool(target) - tt.setTool(number, t2) - tt.setTool(target, t1) - if listname == self.getCurrentTableName(): - self.saveMainLibrary() - return True, target - - def duplicate(self, number, listname): - """duplicates the selected tool in the selected tool table""" - tt = self.getTableFromName(listname) - tool = tt.getTool(number).copy() - tt.addTools(tool) - - newID = list(tt.Tools)[-1] - - if listname == self.getCurrentTableName(): - self.saveMainLibrary() - return True, newID - - def moveToTable(self, number, listname): - """Moves the tool to selected tool table""" - fromTable = self.getTableFromName(self.getCurrentTableName()) - toTable = self.getTableFromName(listname) - tool = fromTable.getTool(number).copy() - toTable.addTools(tool) - fromTable.deleteTool(number) - - def delete(self, number, listname): - """deletes a tool from the current list""" - tt = self.getTableFromName(listname) - tt.deleteTool(number) - if listname == self.getCurrentTableName(): - self.saveMainLibrary() - return True diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index fa46905689..11ce84ad09 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -23,12 +23,9 @@ import FreeCAD from FreeCAD import Vector -from PathScripts import PathLog from PySide import QtCore -from PySide import QtGui import Path -import PathScripts.PathGeom as PathGeom -import PathScripts.PathJob as PathJob +import Path.Main.Job as PathJob import math from numpy import linspace @@ -43,10 +40,10 @@ translate = FreeCAD.Qt.translate if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) UserInput = None @@ -65,6 +62,7 @@ def waiting_effects(function): def new_function(*args, **kwargs): if not FreeCAD.GuiUp: return function(*args, **kwargs) + from PySide import QtGui QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) res = None try: @@ -99,7 +97,7 @@ def loopdetect(obj, edge1, edge2): edge2 = edge """ - PathLog.track() + Path.Log.track() candidates = [] for wire in obj.Shape.Wires: for e in wire.Edges: @@ -123,8 +121,8 @@ def horizontalEdgeLoop(obj, edge): loops = [ w for w in wires - if all(PathGeom.isHorizontal(e) for e in w.Edges) - and PathGeom.isHorizontal(Part.Face(w)) + if all(Path.Geom.isHorizontal(e) for e in w.Edges) + and Path.Geom.isHorizontal(Part.Face(w)) ] if len(loops) == 1: return loops[0] @@ -147,7 +145,7 @@ def horizontalFaceLoop(obj, face, faceList=None): faces = [ "Face%d" % (i + 1) for i, f in enumerate(obj.Shape.Faces) - if any(e.hashCode() in hashes for e in f.Edges) and PathGeom.isVertical(f) + if any(e.hashCode() in hashes for e in f.Edges) and Path.Geom.isVertical(f) ] if faceList and not all(f in faces for f in faceList): @@ -162,7 +160,7 @@ def horizontalFaceLoop(obj, face, faceList=None): # trace-backs single edge spikes don't contribute to the bound box uniqueEdges = [] for edge in outline.Edges: - if any(PathGeom.edgesMatch(edge, e) for e in uniqueEdges): + if any(Path.Geom.edgesMatch(edge, e) for e in uniqueEdges): continue uniqueEdges.append(edge) w = Part.Wire(uniqueEdges) @@ -173,10 +171,10 @@ def horizontalFaceLoop(obj, face, faceList=None): bb2 = w.BoundBox if ( w.isClosed() - and PathGeom.isRoughly(bb1.XMin, bb2.XMin) - and PathGeom.isRoughly(bb1.XMax, bb2.XMax) - and PathGeom.isRoughly(bb1.YMin, bb2.YMin) - and PathGeom.isRoughly(bb1.YMax, bb2.YMax) + and Path.Geom.isRoughly(bb1.XMin, bb2.XMin) + and Path.Geom.isRoughly(bb1.XMax, bb2.XMax) + and Path.Geom.isRoughly(bb1.YMin, bb2.YMin) + and Path.Geom.isRoughly(bb1.YMax, bb2.YMax) ): return faces return None @@ -184,7 +182,7 @@ def horizontalFaceLoop(obj, face, faceList=None): def filterArcs(arcEdge): """filterArcs(Edge) -used to split an arc that is over 180 degrees. Returns list""" - PathLog.track() + Path.Log.track() splitlist = [] if isinstance(arcEdge.Curve, Part.Circle): angle = abs(arcEdge.LastParameter - arcEdge.FirstParameter) # Angle in radians @@ -225,7 +223,7 @@ def makeWorkplane(shape): """ Creates a workplane circle at the ZMin level. """ - PathLog.track() + Path.Log.track() loc = Vector(shape.BoundBox.Center.x, shape.BoundBox.Center.y, shape.BoundBox.ZMin) c = Part.makeCircle(10, loc) return c @@ -240,20 +238,20 @@ def getEnvelope(partshape, subshape=None, depthparams=None): partshape = solid object stockheight = float - Absolute Z height of the top of material before cutting. """ - PathLog.track(partshape, subshape, depthparams) + Path.Log.track(partshape, subshape, depthparams) zShift = 0 if subshape is not None: if isinstance(subshape, Part.Face): - PathLog.debug("processing a face") + Path.Log.debug("processing a face") sec = Part.makeCompound([subshape]) else: area = Path.Area(Fill=2, Coplanar=0).add(subshape) area.setPlane(makeWorkplane(partshape)) - PathLog.debug("About to section with params: {}".format(area.getParams())) + Path.Log.debug("About to section with params: {}".format(area.getParams())) sec = area.makeSections(heights=[0.0], project=True)[0].getShape() - PathLog.debug( + Path.Log.debug( "partshapeZmin: {}, subshapeZMin: {}, zShift: {}".format( partshape.BoundBox.ZMin, subshape.BoundBox.ZMin, zShift ) @@ -269,7 +267,7 @@ def getEnvelope(partshape, subshape=None, depthparams=None): if depthparams is not None: eLength = depthparams.safe_height - depthparams.final_depth zShift = depthparams.final_depth - sec.BoundBox.ZMin - PathLog.debug( + Path.Log.debug( "boundbox zMIN: {} elength: {} zShift {}".format( partshape.BoundBox.ZMin, eLength, zShift ) @@ -283,7 +281,7 @@ def getEnvelope(partshape, subshape=None, depthparams=None): # Extrude the section to top of Boundbox or desired height envelopeshape = sec.extrude(Vector(0, 0, eLength)) - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: + if Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG: removalshape = FreeCAD.ActiveDocument.addObject("Part::Feature", "Envelope") removalshape.Shape = envelopeshape return envelopeshape @@ -300,10 +298,10 @@ def getOffsetArea( ): """Make an offset area of a shape, projected onto a plane. Positive offsets expand the area, negative offsets shrink it. - Inspired by _buildPathArea() from PathAreaOp.py module. Adjustments made + Inspired by _buildPathArea() from Path.Op.Area.py module. Adjustments made based on notes by @sliptonic at this webpage: https://github.com/sliptonic/FreeCAD/wiki/PathArea-notes.""" - PathLog.debug("getOffsetArea()") + Path.Log.debug("getOffsetArea()") areaParams = {} areaParams["Offset"] = offset @@ -363,7 +361,7 @@ def getToolControllers(obj, proxy=None): except Exception: job = None - PathLog.debug("op={} ({})".format(obj.Label, type(obj))) + Path.Log.debug("op={} ({})".format(obj.Label, type(obj))) if job: return [tc for tc in job.Tools.Group if proxy.isToolSupported(obj, tc.Tool)] return [] @@ -374,7 +372,7 @@ def findToolController(obj, proxy, name=None): If no name is specified, returns the first controller. if no controller is found, returns None""" - PathLog.track("name: {}".format(name)) + Path.Log.track("name: {}".format(name)) c = None if UserInput: c = UserInput.selectedToolController() @@ -401,7 +399,7 @@ def findToolController(obj, proxy, name=None): def findParentJob(obj): """retrieves a parent job object for an operation or other Path object""" - PathLog.track() + Path.Log.track() for i in obj.InList: if hasattr(i, "Proxy") and isinstance(i.Proxy, PathJob.ObjectJob): return i @@ -427,7 +425,7 @@ def addToJob(obj, jobname=None): """adds a path object to a job obj = obj jobname = None""" - PathLog.track(jobname) + Path.Log.track(jobname) job = None if jobname is not None: @@ -435,7 +433,7 @@ def addToJob(obj, jobname=None): if len(jobs) == 1: job = jobs[0] else: - PathLog.error(translate("Path", "Didn't find job {}".format(jobname))) + Path.Log.error(translate("Path", "Didn't find job {}".format(jobname))) return None else: jobs = GetJobs() @@ -542,18 +540,14 @@ def guessDepths(objshape, subs=None): def drillTipLength(tool): """returns the length of the drillbit tip.""" - if isinstance(tool, Path.Tool): - PathLog.error(translate("Path", "Legacy Tools not supported")) - return 0.0 - if not hasattr(tool, "TipAngle"): - PathLog.error(translate("Path", "Selected tool is not a drill")) + Path.Log.error(translate("Path", "Selected tool is not a drill")) return 0.0 angle = tool.TipAngle if angle <= 0 or angle >= 180: - PathLog.error( + Path.Log.error( translate("Path", "Invalid Cutting Edge Angle %.2f, must be >0° and <=180°") % angle ) @@ -563,7 +557,7 @@ def drillTipLength(tool): length = (float(tool.Diameter) / 2) / math.tan(theta / 2) if length < 0: - PathLog.error( + Path.Log.error( translate( "Path", "Cutting Edge Angle (%.2f) results in negative tool tip length" ) @@ -726,7 +720,7 @@ class depth_params(object): def __filter_roughly_equal_depths(self, depths): """Depths arrive sorted from largest to smallest, positive to negative. - Return unique list of depths, using PathGeom.isRoughly() method to determine + Return unique list of depths, using Path.Geom.isRoughly() method to determine if the two values are equal. Only one of two consecutive equals are removed. The assumption is that there are not enough consecutively roughly-equal depths @@ -736,7 +730,7 @@ class depth_params(object): depthcopy = sorted(depths) # make a copy and sort low to high keep = [depthcopy[0]] for depth in depthcopy[1:]: - if not PathGeom.isRoughly(depth, keep[-1]): + if not Path.Geom.isRoughly(depth, keep[-1]): keep.append(depth) keep.reverse() # reverse results back high to low return keep diff --git a/src/Mod/Path/PathScripts/PathUtilsGui.py b/src/Mod/Path/PathScripts/PathUtilsGui.py index 98a70a47af..8e27ecc2c1 100644 --- a/src/Mod/Path/PathScripts/PathUtilsGui.py +++ b/src/Mod/Path/PathScripts/PathUtilsGui.py @@ -22,18 +22,18 @@ import FreeCADGui import FreeCAD -import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts -import PathScripts.PathJobCmd as PathJobCmd +import Path +import Path.Main.Gui.JobCmd as PathJobCmd +import Path.Tool.Controller as PathToolController +import PathGui import PathScripts.PathUtils as PathUtils from PySide import QtGui -import PathScripts.PathLog as PathLog if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) translate = FreeCAD.Qt.translate @@ -46,7 +46,7 @@ class PathUtilsUserInput(object): for sel in FreeCADGui.Selection.getSelectionEx(): if hasattr(sel.Object, "Proxy"): if isinstance( - sel.Object.Proxy, PathScripts.PathToolController.ToolController + sel.Object.Proxy, PathToolController.ToolController ): if tc is None: tc = sel.Object diff --git a/src/Mod/Path/PathScripts/README.md b/src/Mod/Path/PathScripts/README.md index b1ada3c2d6..7ce3416f40 100644 --- a/src/Mod/Path/PathScripts/README.md +++ b/src/Mod/Path/PathScripts/README.md @@ -1,3 +1,9 @@ +This is a legacy directory. The remaining files in here should either get refactored so +they can move into the new structure or removed. + +The PropertyBag diversion files are here in order to keep existing ToolBit files working. +They might get removed in future versions. + ### Assigned Accel Keys: * `P,I` ... Launch Path Inspector * `P,J` ... Create Job diff --git a/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp b/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp index 5809ffe250..9d1cc842f0 100644 --- a/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp +++ b/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp @@ -22,7 +22,6 @@ #include "PreCompiled.h" -#include #include #include #include diff --git a/src/Mod/Path/PathTests/PathTestUtils.py b/src/Mod/Path/PathTests/PathTestUtils.py index 492d44f77a..5df774fd71 100644 --- a/src/Mod/Path/PathTests/PathTestUtils.py +++ b/src/Mod/Path/PathTests/PathTestUtils.py @@ -22,7 +22,7 @@ import FreeCAD import Part -import PathScripts.PathGeom as PathGeom +import Path import math import unittest @@ -73,11 +73,11 @@ class PathTestBase(unittest.TestCase): self.assertCoincide(edge.valueAt(edge.FirstParameter), pt1) self.assertCoincide(edge.valueAt(edge.LastParameter), pt2) ptm = edge.valueAt((edge.LastParameter + edge.FirstParameter) / 2) - side = PathGeom.Side.of(pt2 - pt1, ptm - pt1) + side = Path.Geom.Side.of(pt2 - pt1, ptm - pt1) if "CW" == direction: - self.assertEqual(side, PathGeom.Side.Left) + self.assertEqual(side, Path.Geom.Side.Left) else: - self.assertEqual(side, PathGeom.Side.Right) + self.assertEqual(side, Path.Geom.Side.Right) def assertCircle(self, edge, pt, r): """Verivy that edge is a circle at given location.""" @@ -162,7 +162,7 @@ class PathTestBase(unittest.TestCase): e.FirstParameter + (e.LastParameter - e.FirstParameter) * fraction ) - if PathGeom.pointsCoincide(e1.Vertexes[0].Point, e2.Vertexes[0].Point): + if Path.Geom.pointsCoincide(e1.Vertexes[0].Point, e2.Vertexes[0].Point): self.assertCoincide(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point) self.assertCoincide(valueAt(e1, 0.10), valueAt(e2, 0.10)) self.assertCoincide(valueAt(e1, 0.20), valueAt(e2, 0.20)) diff --git a/src/Mod/Path/PathTests/TestCentroidPost.py b/src/Mod/Path/PathTests/TestCentroidPost.py index c77f133c88..ab617838f9 100644 --- a/src/Mod/Path/PathTests/TestCentroidPost.py +++ b/src/Mod/Path/PathTests/TestCentroidPost.py @@ -25,15 +25,13 @@ from importlib import reload import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils -from PathScripts.post import centroid_post as postprocessor +from Path.Post.scripts import centroid_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestCentroidPost(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestGrblPost.py b/src/Mod/Path/PathTests/TestGrblPost.py index 24ff17a9af..ebc9c6234f 100644 --- a/src/Mod/Path/PathTests/TestGrblPost.py +++ b/src/Mod/Path/PathTests/TestGrblPost.py @@ -22,16 +22,14 @@ import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils from importlib import reload -from PathScripts.post import grbl_post as postprocessor +from Path.Post.scripts import grbl_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestGrblPost(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestLinuxCNCPost.py b/src/Mod/Path/PathTests/TestLinuxCNCPost.py index 003865ba00..0706ca8b75 100644 --- a/src/Mod/Path/PathTests/TestLinuxCNCPost.py +++ b/src/Mod/Path/PathTests/TestLinuxCNCPost.py @@ -22,16 +22,13 @@ import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils from importlib import reload -from PathScripts.post import linuxcnc_post as postprocessor +from Path.Post.scripts import linuxcnc_post as postprocessor - -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestLinuxCNCPost(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestMach3Mach4Post.py b/src/Mod/Path/PathTests/TestMach3Mach4Post.py index 3902734e06..0eee4287f8 100644 --- a/src/Mod/Path/PathTests/TestMach3Mach4Post.py +++ b/src/Mod/Path/PathTests/TestMach3Mach4Post.py @@ -25,15 +25,13 @@ from importlib import reload import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils -from PathScripts.post import mach3_mach4_post as postprocessor +from Path.Post.scripts import mach3_mach4_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestMach3Mach4Post(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestPathAdaptive.py b/src/Mod/Path/PathTests/TestPathAdaptive.py index caac814be1..62b0322ca3 100644 --- a/src/Mod/Path/PathTests/TestPathAdaptive.py +++ b/src/Mod/Path/PathTests/TestPathAdaptive.py @@ -24,14 +24,13 @@ import FreeCAD import Part -import PathScripts.PathJob as PathJob -import PathScripts.PathAdaptive as PathAdaptive -import PathScripts.PathGeom as PathGeom +import Path.Op.Adaptive as PathAdaptive +import Path.Main.Job as PathJob from PathTests.PathTestUtils import PathTestBase if FreeCAD.GuiUp: - import PathScripts.PathAdaptiveGui as PathAdaptiveGui - import PathScripts.PathJobGui as PathJobGui + import Path.Main.gui.Job as PathJobGui + import Path.Op.Gui.Adaptive as PathAdaptiveGui class TestPathAdaptive(PathTestBase): diff --git a/src/Mod/Path/PathTests/TestPathCore.py b/src/Mod/Path/PathTests/TestPathCore.py index e27cb26a55..fdcc5d913e 100644 --- a/src/Mod/Path/PathTests/TestPathCore.py +++ b/src/Mod/Path/PathTests/TestPathCore.py @@ -130,40 +130,6 @@ G0 Z0.500000 p.setFromGCode(lines) self.assertEqual(p.toGCode(), output) - def test20(self): - """Test Path Tool and ToolTable object core functionality""" - - t1 = Path.Tool() - self.assertIsInstance(t1, Path.Tool) - - t1.Name = "12.7mm Drill Bit" - self.assertEqual(t1.Name, "12.7mm Drill Bit") - self.assertEqual(t1.ToolType, "Undefined") - t1.ToolType = "Drill" - self.assertEqual(t1.ToolType, "Drill") - t1.Diameter = 12.7 - t1.LengthOffset = 127 - t1.CuttingEdgeAngle = 59 - t1.CuttingEdgeHeight = 50.8 - - self.assertEqual(t1.Diameter, 12.7) - self.assertEqual(t1.LengthOffset, 127) - self.assertEqual(t1.CuttingEdgeAngle, 59) - self.assertEqual(t1.CuttingEdgeHeight, 50.8) - - t2 = Path.Tool("my other tool", tooltype="EndMill", diameter=10) - table = Path.Tooltable() - self.assertIsInstance(table, Path.Tooltable) - table.addTools(t1) - table.addTools(t2) - - self.assertEqual(len(table.Tools), 2) - # gcc7 build needs some special treatment (makes 1L out of a 1) ... - if str(table.Tools) != "{1L: Tool 12.7mm Drill Bit, 2L: Tool my other tool}": - self.assertEqual( - str(table.Tools), "{1: Tool 12.7mm Drill Bit, 2: Tool my other tool}" - ) - def test50(self): """Test Path.Length calculation""" commands = [] diff --git a/src/Mod/Path/PathTests/TestPathDeburr.py b/src/Mod/Path/PathTests/TestPathDeburr.py index f21bd569b3..716f1feb53 100644 --- a/src/Mod/Path/PathTests/TestPathDeburr.py +++ b/src/Mod/Path/PathTests/TestPathDeburr.py @@ -21,18 +21,24 @@ # *************************************************************************** import Path -import PathScripts.PathDeburr as PathDeburr -import PathScripts.PathLog as PathLog +import Path.Op.Deburr as PathDeburr +import Path.Tool.Bit as PathToolBit import PathTests.PathTestUtils as PathTestUtils -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +# Path.Log.trackModule(Path.Log.thisModule()) +class MockToolBit(object): + def __init__(self, name="t1", diameter=5.0): + self.Diameter = diameter + self.FlatRadius = 0 + self.CuttingEdgeAngle = 60 + class TestPathDeburr(PathTestUtils.PathTestBase): def test00(self): """Verify chamfer depth and offset for an end mill.""" - tool = Path.Tool() + tool = MockToolBit() tool.Diameter = 20 tool.FlatRadius = 0 tool.CuttingEdgeAngle = 180 @@ -52,7 +58,7 @@ class TestPathDeburr(PathTestUtils.PathTestBase): def test01(self): """Verify chamfer depth and offset for a 90 deg v-bit.""" - tool = Path.Tool() + tool = MockToolBit() tool.FlatRadius = 0 tool.CuttingEdgeAngle = 90 @@ -68,7 +74,7 @@ class TestPathDeburr(PathTestUtils.PathTestBase): def test02(self): """Verify chamfer depth and offset for a 90 deg v-bit with non 0 flat radius.""" - tool = Path.Tool() + tool = MockToolBit() tool.FlatRadius = 0.3 tool.CuttingEdgeAngle = 90 @@ -84,7 +90,7 @@ class TestPathDeburr(PathTestUtils.PathTestBase): def test03(self): """Verify chamfer depth and offset for a 60 deg v-bit with non 0 flat radius.""" - tool = Path.Tool() + tool = MockToolBit() tool.FlatRadius = 10 tool.CuttingEdgeAngle = 60 diff --git a/src/Mod/Path/PathTests/TestPathDressupDogbone.py b/src/Mod/Path/PathTests/TestPathDressupDogbone.py index 7f160c4c24..aea96e434c 100644 --- a/src/Mod/Path/PathTests/TestPathDressupDogbone.py +++ b/src/Mod/Path/PathTests/TestPathDressupDogbone.py @@ -22,9 +22,9 @@ import FreeCAD import Path -import PathScripts.PathDressupDogbone as PathDressupDogbone -import PathScripts.PathJob as PathJob -import PathScripts.PathProfileFaces as PathProfileFaces +import Path.Dressup.Gui.Dogbone as PathDressupDogbone +import Path.Main.Job as PathJob +import Path.Op.Profile as PathProfile from PathTests.PathTestUtils import PathTestBase @@ -135,7 +135,7 @@ class TestDressupDogbone(PathTestBase): PathJob.Create("Job", [cut], None) - profile = PathProfileFaces.Create("Profile Faces") + profile = PathProfile.Create("Profile") profile.Base = (cut, face) profile.StepDown = 5 # set start and final depth in order to eliminate effects of stock (and its default values) diff --git a/src/Mod/Path/PathTests/TestPathDressupHoldingTags.py b/src/Mod/Path/PathTests/TestPathDressupHoldingTags.py index 103e9f56fa..713a516b2e 100644 --- a/src/Mod/Path/PathTests/TestPathDressupHoldingTags.py +++ b/src/Mod/Path/PathTests/TestPathDressupHoldingTags.py @@ -24,7 +24,7 @@ import PathTests.PathTestUtils as PathTestUtils import math from FreeCAD import Vector -from PathScripts.PathDressupHoldingTags import Tag +from Path.Dressup.Tags import Tag class TestHoldingTags(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestPathDrillGenerator.py b/src/Mod/Path/PathTests/TestPathDrillGenerator.py index f3c94bac61..15ae13bd8b 100644 --- a/src/Mod/Path/PathTests/TestPathDrillGenerator.py +++ b/src/Mod/Path/PathTests/TestPathDrillGenerator.py @@ -20,15 +20,14 @@ # * * # *************************************************************************** -import Path import FreeCAD -import Generators.drill_generator as generator -import PathScripts.PathLog as PathLog -import PathTests.PathTestUtils as PathTestUtils import Part +import Path +import Path.Base.Generator.drill as generator +import PathTests.PathTestUtils as PathTestUtils -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestPathDrillGenerator(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestPathDrillable.py b/src/Mod/Path/PathTests/TestPathDrillable.py index 24a6549841..f333585e2e 100644 --- a/src/Mod/Path/PathTests/TestPathDrillable.py +++ b/src/Mod/Path/PathTests/TestPathDrillable.py @@ -20,18 +20,17 @@ # * * # *************************************************************************** -# import Path import FreeCAD as App -import PathScripts.PathLog as PathLog +import Path +import Path.Base.Drillable as Drillable import PathTests.PathTestUtils as PathTestUtils -import PathScripts.drillableLib as drillableLib if False: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) + Path.Log.trackModule(Path.Log.thisModule()) else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) class TestPathDrillable(PathTestUtils.PathTestBase): @@ -48,17 +47,17 @@ class TestPathDrillable(PathTestUtils.PathTestBase): # Vec and origin v1 = App.Vector(0, 0, 10) v2 = App.Vector(0, 0, 0) - self.assertTrue(drillableLib.compareVecs(v1, v2)) + self.assertTrue(Drillable.compareVecs(v1, v2)) # two valid vectors v1 = App.Vector(0, 10, 0) v2 = App.Vector(0, 20, 0) - self.assertTrue(drillableLib.compareVecs(v1, v2)) + self.assertTrue(Drillable.compareVecs(v1, v2)) # two valid vectors not aligned v1 = App.Vector(0, 10, 0) v2 = App.Vector(10, 0, 0) - self.assertFalse(drillableLib.compareVecs(v1, v2)) + self.assertFalse(Drillable.compareVecs(v1, v2)) def test10(self): """Test isDrillable""" @@ -66,7 +65,7 @@ class TestPathDrillable(PathTestUtils.PathTestBase): # Invalid types candidate = self.obj.getSubObject("Vertex1") self.assertRaises( - TypeError, lambda: drillableLib.isDrillable(self.obj.Shape, candidate) + TypeError, lambda: Drillable.isDrillable(self.obj.Shape, candidate) ) # Test cylinder faces @@ -75,46 +74,46 @@ class TestPathDrillable(PathTestUtils.PathTestBase): candidate = self.obj.getSubObject("Face30") # Typical drilling - self.assertTrue(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate)) # Drilling with smaller bit self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, tooldiameter=20) + Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=20) ) # Drilling with bit too large self.assertFalse( - drillableLib.isDrillable(self.obj.Shape, candidate, tooldiameter=30) + Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=30) ) # off-axis hole candidate = self.obj.getSubObject("Face44") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # Passing explicit vector self.assertTrue( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, vector=App.Vector(0, -1, 0) ) ) # Drilling with smaller bit self.assertTrue( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, tooldiameter=10, vector=App.Vector(0, -1, 0) ) ) # Drilling with bit too large self.assertFalse( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, tooldiameter=30, vector=App.Vector(0, -1, 0) ) ) @@ -123,76 +122,76 @@ class TestPathDrillable(PathTestUtils.PathTestBase): candidate = self.obj.getSubObject("Face29") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertFalse( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # raised cylinder candidate = self.obj.getSubObject("Face32") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertFalse( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # cylinder on slope candidate = self.obj.getSubObject("Face24") # Typical drilling - self.assertTrue(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # Circular Faces candidate = self.obj.getSubObject("Face54") # Typical drilling - self.assertTrue(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # Passing explicit vector self.assertTrue( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, vector=App.Vector(0, 0, 1) ) ) # Drilling with smaller bit self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, tooldiameter=10) + Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=10) ) # Drilling with bit too large self.assertFalse( - drillableLib.isDrillable(self.obj.Shape, candidate, tooldiameter=30) + Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=30) ) # off-axis circular face hole candidate = self.obj.getSubObject("Face58") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # Passing explicit vector self.assertTrue( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, vector=App.Vector(0, -1, 0) ) ) @@ -200,31 +199,31 @@ class TestPathDrillable(PathTestUtils.PathTestBase): # raised face candidate = self.obj.getSubObject("Face49") # Typical drilling - self.assertTrue(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # interrupted Face candidate = self.obj.getSubObject("Face50") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertFalse( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # donut face candidate = self.obj.getSubObject("Face48") # Typical drilling - self.assertTrue(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # Test edges @@ -232,28 +231,28 @@ class TestPathDrillable(PathTestUtils.PathTestBase): candidate = self.obj.getSubObject("Edge55") # Typical drilling - self.assertTrue(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # Passing explicit vector self.assertTrue( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, vector=App.Vector(0, 0, 1) ) ) # Drilling with smaller bit self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, tooldiameter=10) + Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=10) ) # Drilling with bit too large self.assertFalse( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, tooldiameter=30, vector=None ) ) @@ -262,16 +261,16 @@ class TestPathDrillable(PathTestUtils.PathTestBase): candidate = self.obj.getSubObject("Edge74") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertTrue( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # Passing explicit vector self.assertTrue( - drillableLib.isDrillable( + Drillable.isDrillable( self.obj.Shape, candidate, vector=App.Vector(0, 1, 0) ) ) @@ -279,32 +278,32 @@ class TestPathDrillable(PathTestUtils.PathTestBase): # incomplete circular edge candidate = self.obj.getSubObject("Edge39") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertFalse( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) # elliptical edge candidate = self.obj.getSubObject("Edge56") # Typical drilling - self.assertFalse(drillableLib.isDrillable(self.obj.Shape, candidate)) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate)) # Passing None as vector self.assertFalse( - drillableLib.isDrillable(self.obj.Shape, candidate, vector=None) + Drillable.isDrillable(self.obj.Shape, candidate, vector=None) ) def test20(self): """Test getDrillableTargets""" - results = drillableLib.getDrillableTargets(self.obj) + results = Drillable.getDrillableTargets(self.obj) self.assertEqual(len(results), 15) - results = drillableLib.getDrillableTargets(self.obj, vector=None) + results = Drillable.getDrillableTargets(self.obj, vector=None) self.assertEqual(len(results), 20) - results = drillableLib.getDrillableTargets( + results = Drillable.getDrillableTargets( self.obj, ToolDiameter=20, vector=None ) self.assertEqual(len(results), 5) diff --git a/src/Mod/Path/PathTests/TestPathGeom.py b/src/Mod/Path/PathTests/TestPathGeom.py index 87c93f5852..0a2fa38ef6 100644 --- a/src/Mod/Path/PathTests/TestPathGeom.py +++ b/src/Mod/Path/PathTests/TestPathGeom.py @@ -22,7 +22,6 @@ import Part import Path -import PathScripts.PathGeom as PathGeom import math from FreeCAD import Vector @@ -34,186 +33,186 @@ class TestPathGeom(PathTestBase): def test00(self): """Verify getAngle functionality.""" - self.assertRoughly(PathGeom.getAngle(Vector(1, 0, 0)), 0) - self.assertRoughly(PathGeom.getAngle(Vector(1, 1, 0)), math.pi / 4) - self.assertRoughly(PathGeom.getAngle(Vector(0, 1, 0)), math.pi / 2) - self.assertRoughly(PathGeom.getAngle(Vector(-1, 1, 0)), 3 * math.pi / 4) - self.assertRoughly(PathGeom.getAngle(Vector(-1, 0, 0)), math.pi) - self.assertRoughly(PathGeom.getAngle(Vector(-1, -1, 0)), -3 * math.pi / 4) - self.assertRoughly(PathGeom.getAngle(Vector(0, -1, 0)), -math.pi / 2) - self.assertRoughly(PathGeom.getAngle(Vector(1, -1, 0)), -math.pi / 4) + self.assertRoughly(Path.Geom.getAngle(Vector(1, 0, 0)), 0) + self.assertRoughly(Path.Geom.getAngle(Vector(1, 1, 0)), math.pi / 4) + self.assertRoughly(Path.Geom.getAngle(Vector(0, 1, 0)), math.pi / 2) + self.assertRoughly(Path.Geom.getAngle(Vector(-1, 1, 0)), 3 * math.pi / 4) + self.assertRoughly(Path.Geom.getAngle(Vector(-1, 0, 0)), math.pi) + self.assertRoughly(Path.Geom.getAngle(Vector(-1, -1, 0)), -3 * math.pi / 4) + self.assertRoughly(Path.Geom.getAngle(Vector(0, -1, 0)), -math.pi / 2) + self.assertRoughly(Path.Geom.getAngle(Vector(1, -1, 0)), -math.pi / 4) def test01(self): """Verify diffAngle functionality.""" self.assertRoughly( - PathGeom.diffAngle(0, +0 * math.pi / 4, "CW") / math.pi, 0 / 4.0 + Path.Geom.diffAngle(0, +0 * math.pi / 4, "CW") / math.pi, 0 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(0, +3 * math.pi / 4, "CW") / math.pi, 5 / 4.0 + Path.Geom.diffAngle(0, +3 * math.pi / 4, "CW") / math.pi, 5 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(0, -3 * math.pi / 4, "CW") / math.pi, 3 / 4.0 + Path.Geom.diffAngle(0, -3 * math.pi / 4, "CW") / math.pi, 3 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(0, +4 * math.pi / 4, "CW") / math.pi, 4 / 4.0 + Path.Geom.diffAngle(0, +4 * math.pi / 4, "CW") / math.pi, 4 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(0, +0 * math.pi / 4, "CCW") / math.pi, 0 / 4.0 + Path.Geom.diffAngle(0, +0 * math.pi / 4, "CCW") / math.pi, 0 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(0, +3 * math.pi / 4, "CCW") / math.pi, 3 / 4.0 + Path.Geom.diffAngle(0, +3 * math.pi / 4, "CCW") / math.pi, 3 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(0, -3 * math.pi / 4, "CCW") / math.pi, 5 / 4.0 + Path.Geom.diffAngle(0, -3 * math.pi / 4, "CCW") / math.pi, 5 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(0, +4 * math.pi / 4, "CCW") / math.pi, 4 / 4.0 + Path.Geom.diffAngle(0, +4 * math.pi / 4, "CCW") / math.pi, 4 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(+math.pi / 4, +0 * math.pi / 4, "CW") / math.pi, 1 / 4.0 + Path.Geom.diffAngle(+math.pi / 4, +0 * math.pi / 4, "CW") / math.pi, 1 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(+math.pi / 4, +3 * math.pi / 4, "CW") / math.pi, 6 / 4.0 + Path.Geom.diffAngle(+math.pi / 4, +3 * math.pi / 4, "CW") / math.pi, 6 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(+math.pi / 4, -1 * math.pi / 4, "CW") / math.pi, 2 / 4.0 + Path.Geom.diffAngle(+math.pi / 4, -1 * math.pi / 4, "CW") / math.pi, 2 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(-math.pi / 4, +0 * math.pi / 4, "CW") / math.pi, 7 / 4.0 + Path.Geom.diffAngle(-math.pi / 4, +0 * math.pi / 4, "CW") / math.pi, 7 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(-math.pi / 4, +3 * math.pi / 4, "CW") / math.pi, 4 / 4.0 + Path.Geom.diffAngle(-math.pi / 4, +3 * math.pi / 4, "CW") / math.pi, 4 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(-math.pi / 4, -1 * math.pi / 4, "CW") / math.pi, 0 / 4.0 + Path.Geom.diffAngle(-math.pi / 4, -1 * math.pi / 4, "CW") / math.pi, 0 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(+math.pi / 4, +0 * math.pi / 4, "CCW") / math.pi, 7 / 4.0 + Path.Geom.diffAngle(+math.pi / 4, +0 * math.pi / 4, "CCW") / math.pi, 7 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(+math.pi / 4, +3 * math.pi / 4, "CCW") / math.pi, 2 / 4.0 + Path.Geom.diffAngle(+math.pi / 4, +3 * math.pi / 4, "CCW") / math.pi, 2 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(+math.pi / 4, -1 * math.pi / 4, "CCW") / math.pi, 6 / 4.0 + Path.Geom.diffAngle(+math.pi / 4, -1 * math.pi / 4, "CCW") / math.pi, 6 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(-math.pi / 4, +0 * math.pi / 4, "CCW") / math.pi, 1 / 4.0 + Path.Geom.diffAngle(-math.pi / 4, +0 * math.pi / 4, "CCW") / math.pi, 1 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(-math.pi / 4, +3 * math.pi / 4, "CCW") / math.pi, 4 / 4.0 + Path.Geom.diffAngle(-math.pi / 4, +3 * math.pi / 4, "CCW") / math.pi, 4 / 4.0 ) self.assertRoughly( - PathGeom.diffAngle(-math.pi / 4, -1 * math.pi / 4, "CCW") / math.pi, 0 / 4.0 + Path.Geom.diffAngle(-math.pi / 4, -1 * math.pi / 4, "CCW") / math.pi, 0 / 4.0 ) def test02(self): """Verify isVertical/isHorizontal for Vector""" - self.assertTrue(PathGeom.isVertical(Vector(0, 0, 1))) - self.assertTrue(PathGeom.isVertical(Vector(0, 0, -1))) - self.assertFalse(PathGeom.isVertical(Vector(1, 0, 1))) - self.assertFalse(PathGeom.isVertical(Vector(1, 0, -1))) + self.assertTrue(Path.Geom.isVertical(Vector(0, 0, 1))) + self.assertTrue(Path.Geom.isVertical(Vector(0, 0, -1))) + self.assertFalse(Path.Geom.isVertical(Vector(1, 0, 1))) + self.assertFalse(Path.Geom.isVertical(Vector(1, 0, -1))) - self.assertTrue(PathGeom.isHorizontal(Vector(1, 0, 0))) - self.assertTrue(PathGeom.isHorizontal(Vector(-1, 0, 0))) - self.assertTrue(PathGeom.isHorizontal(Vector(0, 1, 0))) - self.assertTrue(PathGeom.isHorizontal(Vector(0, -1, 0))) - self.assertTrue(PathGeom.isHorizontal(Vector(1, 1, 0))) - self.assertTrue(PathGeom.isHorizontal(Vector(-1, 1, 0))) - self.assertTrue(PathGeom.isHorizontal(Vector(1, -1, 0))) - self.assertTrue(PathGeom.isHorizontal(Vector(-1, -1, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(1, 0, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(-1, 0, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(0, 1, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(0, -1, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(1, 1, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(-1, 1, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(1, -1, 0))) + self.assertTrue(Path.Geom.isHorizontal(Vector(-1, -1, 0))) - self.assertFalse(PathGeom.isHorizontal(Vector(0, 1, 1))) - self.assertFalse(PathGeom.isHorizontal(Vector(0, -1, 1))) - self.assertFalse(PathGeom.isHorizontal(Vector(0, 1, -1))) - self.assertFalse(PathGeom.isHorizontal(Vector(0, -1, -1))) + self.assertFalse(Path.Geom.isHorizontal(Vector(0, 1, 1))) + self.assertFalse(Path.Geom.isHorizontal(Vector(0, -1, 1))) + self.assertFalse(Path.Geom.isHorizontal(Vector(0, 1, -1))) + self.assertFalse(Path.Geom.isHorizontal(Vector(0, -1, -1))) def test03(self): """Verify isVertical/isHorizontal for Edges""" # lines self.assertTrue( - PathGeom.isVertical( + Path.Geom.isVertical( Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, -1, 8))) ) ) self.assertFalse( - PathGeom.isVertical( + Path.Geom.isVertical( Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(1, -1, 8))) ) ) self.assertFalse( - PathGeom.isVertical( + Path.Geom.isVertical( Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, 1, 8))) ) ) self.assertTrue( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.LineSegment(Vector(1, -1, -1), Vector(-1, -1, -1))) ) ) self.assertTrue( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.LineSegment(Vector(-1, 1, -1), Vector(-1, -1, -1))) ) ) self.assertTrue( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.LineSegment(Vector(1, 1, -1), Vector(-1, -1, -1))) ) ) self.assertFalse( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.LineSegment(Vector(1, -1, -1), Vector(1, -1, 8))) ) ) self.assertFalse( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.LineSegment(Vector(-1, 1, -1), Vector(-1, 1, 8))) ) ) # circles self.assertTrue( - PathGeom.isVertical( + Path.Geom.isVertical( Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 0))) ) ) self.assertTrue( - PathGeom.isVertical( + Path.Geom.isVertical( Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 0))) ) ) self.assertTrue( - PathGeom.isVertical( + Path.Geom.isVertical( Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 0))) ) ) self.assertFalse( - PathGeom.isVertical( + Path.Geom.isVertical( Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1))) ) ) self.assertTrue( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 0, 1))) ) ) self.assertFalse( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 1))) ) ) self.assertFalse( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 1))) ) ) self.assertFalse( - PathGeom.isHorizontal( + Path.Geom.isHorizontal( Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1))) ) ) @@ -223,21 +222,21 @@ class TestPathGeom(PathTestBase): # and now I disable the tests because they seem to fail on OCE # bezier = Part.BezierCurve() # bezier.setPoles([Vector(), Vector(1,1,0), Vector(2,1,0), Vector(2,2,0)]) - # self.assertTrue(PathGeom.isHorizontal(Part.Edge(bezier))) - # self.assertFalse(PathGeom.isVertical(Part.Edge(bezier))) + # self.assertTrue(Path.Geom.isHorizontal(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isVertical(Part.Edge(bezier))) # bezier.setPoles([Vector(), Vector(1,1,1), Vector(2,1,0), Vector(2,2,0)]) - # self.assertFalse(PathGeom.isHorizontal(Part.Edge(bezier))) - # self.assertFalse(PathGeom.isVertical(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isHorizontal(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isVertical(Part.Edge(bezier))) # bezier.setPoles([Vector(), Vector(1,1,0), Vector(2,1,1), Vector(2,2,0)]) - # self.assertFalse(PathGeom.isHorizontal(Part.Edge(bezier))) - # self.assertFalse(PathGeom.isVertical(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isHorizontal(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isVertical(Part.Edge(bezier))) # bezier.setPoles([Vector(), Vector(1,1,0), Vector(2,1,0), Vector(2,2,1)]) - # self.assertFalse(PathGeom.isHorizontal(Part.Edge(bezier))) - # self.assertFalse(PathGeom.isVertical(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isHorizontal(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isVertical(Part.Edge(bezier))) # # bezier.setPoles([Vector(), Vector(1,1,1), Vector(2,2,2), Vector(0,0,3)]) - # self.assertFalse(PathGeom.isHorizontal(Part.Edge(bezier))) - # self.assertTrue(PathGeom.isVertical(Part.Edge(bezier))) + # self.assertFalse(Path.Geom.isHorizontal(Part.Edge(bezier))) + # self.assertTrue(Path.Geom.isVertical(Part.Edge(bezier))) def test04(self): """Verify isVertical/isHorizontal for faces""" @@ -250,19 +249,19 @@ class TestPathGeom(PathTestBase): xzPlane = Part.makePlane(100, 100, Vector(), Vector(1, 0, 1)) yzPlane = Part.makePlane(100, 100, Vector(), Vector(0, 1, 1)) - self.assertTrue(PathGeom.isVertical(xPlane)) - self.assertTrue(PathGeom.isVertical(yPlane)) - self.assertFalse(PathGeom.isVertical(zPlane)) - self.assertTrue(PathGeom.isVertical(xyPlane)) - self.assertFalse(PathGeom.isVertical(xzPlane)) - self.assertFalse(PathGeom.isVertical(yzPlane)) + self.assertTrue(Path.Geom.isVertical(xPlane)) + self.assertTrue(Path.Geom.isVertical(yPlane)) + self.assertFalse(Path.Geom.isVertical(zPlane)) + self.assertTrue(Path.Geom.isVertical(xyPlane)) + self.assertFalse(Path.Geom.isVertical(xzPlane)) + self.assertFalse(Path.Geom.isVertical(yzPlane)) - self.assertFalse(PathGeom.isHorizontal(xPlane)) - self.assertFalse(PathGeom.isHorizontal(yPlane)) - self.assertTrue(PathGeom.isHorizontal(zPlane)) - self.assertFalse(PathGeom.isHorizontal(xyPlane)) - self.assertFalse(PathGeom.isHorizontal(xzPlane)) - self.assertFalse(PathGeom.isHorizontal(yzPlane)) + self.assertFalse(Path.Geom.isHorizontal(xPlane)) + self.assertFalse(Path.Geom.isHorizontal(yPlane)) + self.assertTrue(Path.Geom.isHorizontal(zPlane)) + self.assertFalse(Path.Geom.isHorizontal(xyPlane)) + self.assertFalse(Path.Geom.isHorizontal(xzPlane)) + self.assertFalse(Path.Geom.isHorizontal(yzPlane)) # cylinders xCylinder = [ @@ -296,92 +295,92 @@ class TestPathGeom(PathTestBase): if type(f.Surface) == Part.Cylinder ][0] - self.assertTrue(PathGeom.isHorizontal(xCylinder)) - self.assertTrue(PathGeom.isHorizontal(yCylinder)) - self.assertFalse(PathGeom.isHorizontal(zCylinder)) - self.assertTrue(PathGeom.isHorizontal(xyCylinder)) - self.assertFalse(PathGeom.isHorizontal(xzCylinder)) - self.assertFalse(PathGeom.isHorizontal(yzCylinder)) + self.assertTrue(Path.Geom.isHorizontal(xCylinder)) + self.assertTrue(Path.Geom.isHorizontal(yCylinder)) + self.assertFalse(Path.Geom.isHorizontal(zCylinder)) + self.assertTrue(Path.Geom.isHorizontal(xyCylinder)) + self.assertFalse(Path.Geom.isHorizontal(xzCylinder)) + self.assertFalse(Path.Geom.isHorizontal(yzCylinder)) def test07(self): """Verify speed interpolation works for different pitches""" # horizontal self.assertRoughly( - 100, PathGeom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 100, 50) + 100, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 100, 50) ) self.assertRoughly( - 100, PathGeom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 100, 50) + 100, Path.Geom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 100, 50) ) # vertical self.assertRoughly( - 50, PathGeom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 100, 50) + 50, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 100, 50) ) self.assertRoughly( - 50, PathGeom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 100, 50) + 50, Path.Geom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 100, 50) ) # 45° self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 100, 50) + 75, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 100, 50) ) self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 100, 50) + 75, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 100, 50) ) self.assertRoughly( 75, - PathGeom.speedBetweenPoints(Vector(), Vector(0.707, 0.707, 1), 100, 50), + Path.Geom.speedBetweenPoints(Vector(), Vector(0.707, 0.707, 1), 100, 50), 0.01, ) self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 100, 50) + 75, Path.Geom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 100, 50) ) self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 100, 50) + 75, Path.Geom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 100, 50) ) self.assertRoughly( 75, - PathGeom.speedBetweenPoints(Vector(0.707, 0.707, 1), Vector(), 100, 50), + Path.Geom.speedBetweenPoints(Vector(0.707, 0.707, 1), Vector(), 100, 50), 0.01, ) # 30° self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(), Vector(0.5774, 0, 1), 100, 50), + Path.Geom.speedBetweenPoints(Vector(), Vector(0.5774, 0, 1), 100, 50), 0.01, ) self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(), Vector(0, 0.5774, 1), 100, 50), + Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0.5774, 1), 100, 50), 0.01, ) self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(0.5774, 0, 1), Vector(), 100, 50), + Path.Geom.speedBetweenPoints(Vector(0.5774, 0, 1), Vector(), 100, 50), 0.01, ) self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(0, 0.5774, 1), Vector(), 100, 50), + Path.Geom.speedBetweenPoints(Vector(0, 0.5774, 1), Vector(), 100, 50), 0.01, ) # 60° self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(), Vector(1, 0, 0.5774), 100, 50), + Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 0.5774), 100, 50), 0.01, ) self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(), Vector(0, 1, 0.5774), 100, 50), + Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 0.5774), 100, 50), 0.01, ) self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(1, 0, 0.5774), Vector(), 100, 50), + Path.Geom.speedBetweenPoints(Vector(1, 0, 0.5774), Vector(), 100, 50), 0.01, ) self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(0, 1, 0.5774), Vector(), 100, 50), + Path.Geom.speedBetweenPoints(Vector(0, 1, 0.5774), Vector(), 100, 50), 0.01, ) @@ -389,81 +388,81 @@ class TestPathGeom(PathTestBase): """Verify speed interpolation works for different pitches if vSpeed > hSpeed""" # horizontal self.assertRoughly( - 50, PathGeom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 50, 100) + 50, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 50, 100) ) self.assertRoughly( - 50, PathGeom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 50, 100) + 50, Path.Geom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 50, 100) ) # vertical self.assertRoughly( - 100, PathGeom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 50, 100) + 100, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 50, 100) ) self.assertRoughly( - 100, PathGeom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 50, 100) + 100, Path.Geom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 50, 100) ) # 45° self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 50, 100) + 75, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 50, 100) ) self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 50, 100) + 75, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 50, 100) ) self.assertRoughly( 75, - PathGeom.speedBetweenPoints(Vector(), Vector(0.707, 0.707, 1), 50, 100), + Path.Geom.speedBetweenPoints(Vector(), Vector(0.707, 0.707, 1), 50, 100), 0.01, ) self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 50, 100) + 75, Path.Geom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 50, 100) ) self.assertRoughly( - 75, PathGeom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 50, 100) + 75, Path.Geom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 50, 100) ) self.assertRoughly( 75, - PathGeom.speedBetweenPoints(Vector(0.707, 0.707, 1), Vector(), 50, 100), + Path.Geom.speedBetweenPoints(Vector(0.707, 0.707, 1), Vector(), 50, 100), 0.01, ) # 30° self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(), Vector(0.5774, 0, 1), 50, 100), + Path.Geom.speedBetweenPoints(Vector(), Vector(0.5774, 0, 1), 50, 100), 0.01, ) self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(), Vector(0, 0.5774, 1), 50, 100), + Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0.5774, 1), 50, 100), 0.01, ) self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(0.5774, 0, 1), Vector(), 50, 100), + Path.Geom.speedBetweenPoints(Vector(0.5774, 0, 1), Vector(), 50, 100), 0.01, ) self.assertRoughly( 83.33, - PathGeom.speedBetweenPoints(Vector(0, 0.5774, 1), Vector(), 50, 100), + Path.Geom.speedBetweenPoints(Vector(0, 0.5774, 1), Vector(), 50, 100), 0.01, ) # 60° self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(), Vector(1, 0, 0.5774), 50, 100), + Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 0.5774), 50, 100), 0.01, ) self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(), Vector(0, 1, 0.5774), 50, 100), + Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 0.5774), 50, 100), 0.01, ) self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(1, 0, 0.5774), Vector(), 50, 100), + Path.Geom.speedBetweenPoints(Vector(1, 0, 0.5774), Vector(), 50, 100), 0.01, ) self.assertRoughly( 66.66, - PathGeom.speedBetweenPoints(Vector(0, 1, 0.5774), Vector(), 50, 100), + Path.Geom.speedBetweenPoints(Vector(0, 1, 0.5774), Vector(), 50, 100), 0.01, ) @@ -471,12 +470,12 @@ class TestPathGeom(PathTestBase): """Verify proper geometry objects for G1 and G01 commands are created.""" spt = Vector(1, 2, 3) self.assertLine( - PathGeom.edgeForCmd(Path.Command("G1", {"X": 7, "Y": 2, "Z": 3}), spt), + Path.Geom.edgeForCmd(Path.Command("G1", {"X": 7, "Y": 2, "Z": 3}), spt), spt, Vector(7, 2, 3), ) self.assertLine( - PathGeom.edgeForCmd(Path.Command("G01", {"X": 1, "Y": 3, "Z": 5}), spt), + Path.Geom.edgeForCmd(Path.Command("G01", {"X": 1, "Y": 3, "Z": 5}), spt), spt, Vector(1, 3, 5), ) @@ -486,7 +485,7 @@ class TestPathGeom(PathTestBase): p1 = Vector(0, -1, 2) p2 = Vector(-1, 0, 2) self.assertArc( - PathGeom.edgeForCmd( + Path.Geom.edgeForCmd( Path.Command( "G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": 1, "K": 0} ), @@ -497,7 +496,7 @@ class TestPathGeom(PathTestBase): "CW", ) self.assertArc( - PathGeom.edgeForCmd( + Path.Geom.edgeForCmd( Path.Command( "G3", {"X": p1.x, "Y": p1.y, "z": p1.z, "I": -1, "J": 0, "K": 0} ), @@ -514,7 +513,7 @@ class TestPathGeom(PathTestBase): p1 = Vector(0, 1, 0) p2 = Vector(1, 0, 2) self.assertCurve( - PathGeom.edgeForCmd( + Path.Geom.edgeForCmd( Path.Command( "G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": -1, "K": 1} ), @@ -527,7 +526,7 @@ class TestPathGeom(PathTestBase): p1 = Vector(-1, 0, 0) p2 = Vector(0, -1, 2) self.assertCurve( - PathGeom.edgeForCmd( + Path.Geom.edgeForCmd( Path.Command( "G3", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 1, "J": 0, "K": 1} ), @@ -542,7 +541,7 @@ class TestPathGeom(PathTestBase): p1 = Vector(0, -1, 2) p2 = Vector(-1, 0, 0) self.assertCurve( - PathGeom.edgeForCmd( + Path.Geom.edgeForCmd( Path.Command( "G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": 1, "K": -1} ), @@ -555,7 +554,7 @@ class TestPathGeom(PathTestBase): p1 = Vector(-1, 0, 2) p2 = Vector(0, -1, 0) self.assertCurve( - PathGeom.edgeForCmd( + Path.Geom.edgeForCmd( Path.Command( "G3", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 1, "J": 0, "K": -1} ), @@ -574,7 +573,7 @@ class TestPathGeom(PathTestBase): p4 = Vector(+10, 0, 0) def cmds(pa, pb, pc, flip): - return PathGeom.cmdsForEdge(Part.Edge(Part.Arc(pa, pb, pc)), flip)[0] + return Path.Geom.cmdsForEdge(Part.Edge(Part.Arc(pa, pb, pc)), flip)[0] def cmd(g, end, off): return Path.Command( @@ -608,7 +607,7 @@ class TestPathGeom(PathTestBase): def cmds(center, radius, up=True): norm = Vector(0, 0, 1) if up else Vector(0, 0, -1) - return PathGeom.cmdsForEdge(Part.Edge(Part.Circle(center, norm, radius)))[0] + return Path.Geom.cmdsForEdge(Part.Edge(Part.Circle(center, norm, radius)))[0] def cmd(g, end, off): return Path.Command( @@ -633,7 +632,7 @@ class TestPathGeom(PathTestBase): def test42(self): """Verify ellipsis results in a proper segmentation of G1 commands.""" ellipse = Part.Edge(Part.Ellipse()) - cmds = PathGeom.cmdsForEdge(ellipse) + cmds = Path.Geom.cmdsForEdge(ellipse) # let's make sure all commands are G1 and there are more than 20 of those self.assertGreater(len(cmds), 20) self.assertTrue(all([cmd.Name == "G1" for cmd in cmds])) @@ -646,16 +645,16 @@ class TestPathGeom(PathTestBase): commands.append(Path.Command("G0", {"X": 0})) commands.append(Path.Command("G1", {"Y": 0})) - wire, rapid = PathGeom.wireForPath(Path.Path(commands)) + wire, rapid = Path.Geom.wireForPath(Path.Path(commands)) self.assertEqual(len(wire.Edges), 4) self.assertLine(wire.Edges[0], Vector(0, 0, 0), Vector(1, 0, 0)) self.assertLine(wire.Edges[1], Vector(1, 0, 0), Vector(1, 1, 0)) self.assertLine(wire.Edges[2], Vector(1, 1, 0), Vector(0, 1, 0)) self.assertLine(wire.Edges[3], Vector(0, 1, 0), Vector(0, 0, 0)) self.assertEqual(len(rapid), 1) - self.assertTrue(PathGeom.edgesMatch(rapid[0], wire.Edges[2])) + self.assertTrue(Path.Geom.edgesMatch(rapid[0], wire.Edges[2])) - wires = PathGeom.wiresForPath(Path.Path(commands)) + wires = Path.Geom.wiresForPath(Path.Path(commands)) self.assertEqual(len(wires), 2) self.assertEqual(len(wires[0].Edges), 2) self.assertLine(wires[0].Edges[0], Vector(0, 0, 0), Vector(1, 0, 0)) @@ -669,15 +668,15 @@ class TestPathGeom(PathTestBase): p2 = Vector(0, 0, 0) p3 = Vector(10, 10, 0) - e = PathGeom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 0, 2) + e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 0, 2) self.assertCurve(e, p1, p2 + Vector(0, 0, 1), p3 + Vector(0, 0, 2)) - e = PathGeom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 3, 7) + e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 3, 7) self.assertCurve( e, p1 + Vector(0, 0, 3), p2 + Vector(0, 0, 5), p3 + Vector(0, 0, 7) ) - e = PathGeom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 9, 1) + e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 9, 1) self.assertCurve( e, p1 + Vector(0, 0, 9), p2 + Vector(0, 0, 5), p3 + Vector(0, 0, 1) ) @@ -687,16 +686,16 @@ class TestPathGeom(PathTestBase): p12 = p2 + dz p13 = p3 + dz - e = PathGeom.arcToHelix(Part.Edge(Part.Arc(p11, p12, p13)), 0, 8) + e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p11, p12, p13)), 0, 8) self.assertCurve(e, p1, p2 + Vector(0, 0, 4), p3 + Vector(0, 0, 8)) - e = PathGeom.arcToHelix(Part.Edge(Part.Arc(p11, p12, p13)), 2, -2) + e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p11, p12, p13)), 2, -2) self.assertCurve(e, p1 + Vector(0, 0, 2), p2, p3 + Vector(0, 0, -2)) p1 = Vector(10, -10, 1) p2 = Vector(10 - 10 * math.sin(math.pi / 4), -10 * math.cos(math.pi / 4), 1) p3 = Vector(0, 0, 1) - e = PathGeom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 0, 5) + e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 0, 5) self.assertCurve( e, Vector(10, -10, 0), Vector(p2.x, p2.y, 2.5), Vector(0, 0, 5) ) @@ -713,7 +712,7 @@ class TestPathGeom(PathTestBase): p12 = Vector(10 - o, -o, 0) p23 = Vector(10 - o, +o, 0) - e = PathGeom.splitArcAt(arc, p2) + e = Path.Geom.splitArcAt(arc, p2) self.assertCurve(e[0], p1, p12, p2) self.assertCurve(e[1], p2, p23, p3) @@ -724,7 +723,7 @@ class TestPathGeom(PathTestBase): 10 - 10 * math.sin(5 * math.pi / 8), -10 * math.cos(5 * math.pi / 8), 0 ) - e = PathGeom.splitArcAt(arc, p12) + e = Path.Geom.splitArcAt(arc, p12) self.assertCurve(e[0], p1, p34, p12) self.assertCurve(e[1], p12, p45, p3) @@ -732,7 +731,7 @@ class TestPathGeom(PathTestBase): """Verify splitEdgeAt.""" # split a line segment - e = PathGeom.splitEdgeAt( + e = Path.Geom.splitEdgeAt( Part.Edge(Part.LineSegment(Vector(), Vector(2, 4, 6))), Vector(1, 2, 3) ) self.assertLine(e[0], Vector(), Vector(1, 2, 3)) @@ -743,7 +742,7 @@ class TestPathGeom(PathTestBase): p2 = Vector(0, 0, 1) p3 = Vector(10, 10, 1) arc = Part.Edge(Part.Arc(p1, p2, p3)) - e = PathGeom.splitEdgeAt(arc, p2) + e = Path.Geom.splitEdgeAt(arc, p2) o = 10 * math.sin(math.pi / 4) p12 = Vector(10 - o, -o, 1) p23 = Vector(10 - o, +o, 1) @@ -754,10 +753,10 @@ class TestPathGeom(PathTestBase): p1 = Vector(10, -10, 0) p2 = Vector(0, 0, 5) p3 = Vector(10, 10, 10) - h = PathGeom.arcToHelix(arc, 0, 10) + h = Path.Geom.arcToHelix(arc, 0, 10) self.assertCurve(h, p1, p2, p3) - e = PathGeom.splitEdgeAt(h, p2) + e = Path.Geom.splitEdgeAt(h, p2) o = 10 * math.sin(math.pi / 4) p12 = Vector(10 - o, -o, 2.5) p23 = Vector(10 - o, +o, 7.5) @@ -774,7 +773,7 @@ class TestPathGeom(PathTestBase): ac = arc.Curve.Center s = Vector(434.54, 378.26, 1) - head, tail = PathGeom.splitEdgeAt(arc, s) + head, tail = Path.Geom.splitEdgeAt(arc, s) # make sure the arcs connect as they should self.assertCoincide( @@ -802,59 +801,59 @@ class TestPathGeom(PathTestBase): def test70(self): """Flip a line.""" edge = Part.Edge(Part.Line(Vector(0, 0, 0), Vector(3, 2, 1))) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.Edge(Part.Line(Vector(0, 0, 0), Vector(-3, -2, -1))) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) def test71(self): """Flip a line segment.""" edge = Part.Edge(Part.LineSegment(Vector(0, 0, 0), Vector(3, 2, 1))) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.Edge(Part.LineSegment(Vector(4, 2, 1), Vector(-3, -7, 9))) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeLine(Vector(1, 0, 3), Vector(3, 2, 1)) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) def test72(self): """Flip a circle""" edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1)) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, -1)) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) def test73(self): """Flip an arc""" # make sure all 4 quadrants work edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1), 45, 90) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1), 100, 170) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1), 200, 250) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1), 300, 340) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) # and the other way around too edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, -1), 45, 90) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, -1), 100, 170) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, -1), 200, 250) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, -1), 300, 340) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) def test74(self): """Flip a rotated arc""" # oh yes ... edge = Part.makeCircle(3, Vector(1, 3, 2), Vector(0, 0, 1), 45, 90) edge.rotate(edge.Curve.Center, Vector(0, 0, 1), -90) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) def test75(self): """Flip a B-spline""" @@ -863,7 +862,7 @@ class TestPathGeom(PathTestBase): [Vector(1, 2, 3), Vector(-3, 0, 7), Vector(-3, 1, 9), Vector(1, 3, 5)] ) edge = Part.Edge(spline) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) edge = Part.Edge( Part.BSplineCurve( @@ -876,7 +875,7 @@ class TestPathGeom(PathTestBase): weights=[2, 3, 5, 7], ) ) - self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge)) + self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) def test76(self): """Flip an offset wire""" @@ -896,7 +895,7 @@ class TestPathGeom(PathTestBase): e2 = Part.Edge(Part.LineSegment(Vector(0, -7, 0), Vector(-8, 4, 0))) w0 = Part.Wire([e0, e1, e2]) w1 = w0.makeOffset2D(1) - w2 = PathGeom.flipWire(w1) + w2 = Path.Geom.flipWire(w1) # do some sanity checks self.assertTrue(w2.isValid()) self.assertTrue(w2.isClosed()) diff --git a/src/Mod/Path/PathTests/TestPathHelix.py b/src/Mod/Path/PathTests/TestPathHelix.py index c3512571d7..69ce117a0d 100644 --- a/src/Mod/Path/PathTests/TestPathHelix.py +++ b/src/Mod/Path/PathTests/TestPathHelix.py @@ -22,13 +22,13 @@ import Draft import FreeCAD -import PathScripts.PathHelix as PathHelix -import PathScripts.PathJob as PathJob -import PathScripts.PathLog as PathLog +import Path +import Path.Main.Job as PathJob +import Path.Op.Helix as PathHelix import PathTests.PathTestUtils as PathTestUtils -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +# Path.Log.trackModule(Path.Log.thisModule()) class TestPathHelix(PathTestUtils.PathTestBase): @@ -78,7 +78,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): model = base[0] for sub in base[1]: pos = proxy.holePosition(op, model, sub) - # PathLog.track(deg, pos, pos.Length) + # Path.Log.track(deg, pos, pos.Length) self.assertRoughly( round(pos.Length / 10, 0), proxy.holeDiameter(op, model, sub) ) @@ -104,7 +104,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): model = base[0] for sub in base[1]: pos = proxy.holePosition(op, model, sub) - # PathLog.track(deg, pos, pos.Length) + # Path.Log.track(deg, pos, pos.Length) self.assertRoughly( round(pos.Length / 10, 0), proxy.holeDiameter(op, model, sub) ) @@ -130,7 +130,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): model = base[0] for sub in base[1]: pos = proxy.holePosition(op, model, sub) - # PathLog.track(deg, pos, pos.Length) + # Path.Log.track(deg, pos, pos.Length) self.assertRoughly( round(pos.Length / 10, 0), proxy.holeDiameter(op, model, sub) ) diff --git a/src/Mod/Path/PathTests/TestPathHelixGenerator.py b/src/Mod/Path/PathTests/TestPathHelixGenerator.py index c8d6504ca5..274ea84c89 100644 --- a/src/Mod/Path/PathTests/TestPathHelixGenerator.py +++ b/src/Mod/Path/PathTests/TestPathHelixGenerator.py @@ -23,13 +23,12 @@ import FreeCAD import Part import Path -import PathScripts.PathLog as PathLog -import Generators.helix_generator as generator +import Path.Base.Generator.helix as generator import PathTests.PathTestUtils as PathTestUtils -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) def _resetArgs(): diff --git a/src/Mod/Path/PathTests/TestPathHelpers.py b/src/Mod/Path/PathTests/TestPathHelpers.py index 653fafabad..c70b3dabfc 100644 --- a/src/Mod/Path/PathTests/TestPathHelpers.py +++ b/src/Mod/Path/PathTests/TestPathHelpers.py @@ -23,15 +23,24 @@ import FreeCAD import Part import Path -import PathFeedRate -import PathMachineState -import PathScripts.PathGeom as PathGeom -import PathScripts.PathToolController as PathToolController +import Path.Base.FeedRate as PathFeedRate +import Path.Base.MachineState as PathMachineState +import Path.Tool.Bit as PathToolBit +import Path.Tool.Controller as PathToolController import PathScripts.PathUtils as PathUtils from PathTests.PathTestUtils import PathTestBase +def createTool(name="t1", diameter=1.75): + attrs = { + "shape": None, + "name": name, + "parameter": {"Diameter": diameter}, + "attribute": [], + } + return PathToolBit.Factory.CreateFromAttrs(attrs, name) + class TestPathHelpers(PathTestBase): def setUp(self): self.doc = FreeCAD.newDocument("TestPathUtils") @@ -48,7 +57,7 @@ class TestPathHelpers(PathTestBase): def test00(self): """Test that FeedRate Helper populates horiz and vert feed rate based on TC""" - t = Path.Tool("test", "5.0") + t = createTool("test", 5.0) tc = PathToolController.Create("TC0", t) tc.VertRapid = 5 tc.HorizRapid = 10 @@ -124,7 +133,7 @@ class TestPathHelpers(PathTestBase): self.assertTrue(len(results) == 2) e1 = results[0] self.assertTrue(isinstance(e1.Curve, Part.Circle)) - self.assertTrue(PathGeom.pointsCoincide(edge.Curve.Location, e1.Curve.Location)) + self.assertTrue(Path.Geom.pointsCoincide(edge.Curve.Location, e1.Curve.Location)) self.assertTrue(edge.Curve.Radius == e1.Curve.Radius) # filter a 180 degree arc diff --git a/src/Mod/Path/PathTests/TestPathLog.py b/src/Mod/Path/PathTests/TestPathLog.py index a18fe4abc1..50c8100efa 100644 --- a/src/Mod/Path/PathTests/TestPathLog.py +++ b/src/Mod/Path/PathTests/TestPathLog.py @@ -20,7 +20,7 @@ # * * # *************************************************************************** -import PathScripts.PathLog as PathLog +import Path import unittest @@ -30,17 +30,17 @@ class TestPathLog(unittest.TestCase): MODULE = "TestPathLog" # file name without extension def setUp(self): - PathLog.setLevel(PathLog.Level.RESET) - PathLog.untrackAllModules() + Path.Log.setLevel(Path.Log.Level.RESET) + Path.Log.untrackAllModules() def callerFile(self): - return PathLog._caller()[0] + return Path.Log._caller()[0] def callerLine(self): - return PathLog._caller()[1] + return Path.Log._caller()[1] def callerFunc(self): - return PathLog._caller()[2] + return Path.Log._caller()[2] def test00(self): """Check for proper module extraction.""" @@ -52,145 +52,145 @@ class TestPathLog(unittest.TestCase): def test10(self): """Verify default log levels is NOTICE.""" - self.assertEqual(PathLog.getLevel(), PathLog.Level.NOTICE) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.NOTICE) + self.assertEqual(Path.Log.getLevel(), Path.Log.Level.NOTICE) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.NOTICE) def test11(self): """Verify setting global log level.""" - PathLog.setLevel(PathLog.Level.DEBUG) + Path.Log.setLevel(Path.Log.Level.DEBUG) - self.assertEqual(PathLog.getLevel(), PathLog.Level.DEBUG) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + self.assertEqual(Path.Log.getLevel(), Path.Log.Level.DEBUG) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.DEBUG) def test12(self): """Verify setting module log level.""" - PathLog.setLevel(PathLog.Level.DEBUG, self.MODULE) + Path.Log.setLevel(Path.Log.Level.DEBUG, self.MODULE) - self.assertEqual(PathLog.getLevel(), PathLog.Level.NOTICE) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + self.assertEqual(Path.Log.getLevel(), Path.Log.Level.NOTICE) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.DEBUG) def test13(self): """Verify setting other modul's log level doesn't change this one's.""" # if this test fails then most likely the global RESET is broken - PathLog.setLevel(PathLog.Level.DEBUG, "SomeOtherModule") + Path.Log.setLevel(Path.Log.Level.DEBUG, "SomeOtherModule") - self.assertEqual(PathLog.getLevel(), PathLog.Level.NOTICE) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.NOTICE) + self.assertEqual(Path.Log.getLevel(), Path.Log.Level.NOTICE) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.NOTICE) def test14(self): """Verify resetting log level for module falls back to global level.""" - PathLog.setLevel(PathLog.Level.DEBUG, self.MODULE) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + Path.Log.setLevel(Path.Log.Level.DEBUG, self.MODULE) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.DEBUG) # changing global log level does not affect module - PathLog.setLevel(PathLog.Level.ERROR) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + Path.Log.setLevel(Path.Log.Level.ERROR) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.DEBUG) # resetting module log level restores global log level for module - PathLog.setLevel(PathLog.Level.RESET, self.MODULE) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.ERROR) + Path.Log.setLevel(Path.Log.Level.RESET, self.MODULE) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.ERROR) # changing the global log level will also change the module log level - PathLog.setLevel(PathLog.Level.DEBUG) - self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + Path.Log.setLevel(Path.Log.Level.DEBUG) + self.assertEqual(Path.Log.getLevel(self.MODULE), Path.Log.Level.DEBUG) def test20(self): """Verify debug logs aren't logged by default.""" - self.assertIsNone(PathLog.debug("this")) + self.assertIsNone(Path.Log.debug("this")) def test21(self): """Verify debug logs are logged if log level is set to DEBUG.""" - PathLog.setLevel(PathLog.Level.DEBUG) - self.assertIsNotNone(PathLog.debug("this")) + Path.Log.setLevel(Path.Log.Level.DEBUG) + self.assertIsNotNone(Path.Log.debug("this")) def test30(self): """Verify log level ERROR.""" - PathLog.setLevel(PathLog.Level.ERROR) - self.assertIsNone(PathLog.debug("something")) - self.assertIsNone(PathLog.info("something")) - self.assertIsNone(PathLog.notice("something")) - self.assertIsNone(PathLog.warning("something")) - self.assertIsNotNone(PathLog.error("something")) + Path.Log.setLevel(Path.Log.Level.ERROR) + self.assertIsNone(Path.Log.debug("something")) + self.assertIsNone(Path.Log.info("something")) + self.assertIsNone(Path.Log.notice("something")) + self.assertIsNone(Path.Log.warning("something")) + self.assertIsNotNone(Path.Log.error("something")) def test31(self): """Verify log level WARNING.""" - PathLog.setLevel(PathLog.Level.WARNING) - self.assertIsNone(PathLog.debug("something")) - self.assertIsNone(PathLog.info("something")) - self.assertIsNone(PathLog.notice("something")) - self.assertIsNotNone(PathLog.warning("something")) - self.assertIsNotNone(PathLog.error("something")) + Path.Log.setLevel(Path.Log.Level.WARNING) + self.assertIsNone(Path.Log.debug("something")) + self.assertIsNone(Path.Log.info("something")) + self.assertIsNone(Path.Log.notice("something")) + self.assertIsNotNone(Path.Log.warning("something")) + self.assertIsNotNone(Path.Log.error("something")) def test32(self): """Verify log level NOTICE.""" - PathLog.setLevel(PathLog.Level.NOTICE) - self.assertIsNone(PathLog.debug("something")) - self.assertIsNone(PathLog.info("something")) - self.assertIsNotNone(PathLog.notice("something")) - self.assertIsNotNone(PathLog.warning("something")) - self.assertIsNotNone(PathLog.error("something")) + Path.Log.setLevel(Path.Log.Level.NOTICE) + self.assertIsNone(Path.Log.debug("something")) + self.assertIsNone(Path.Log.info("something")) + self.assertIsNotNone(Path.Log.notice("something")) + self.assertIsNotNone(Path.Log.warning("something")) + self.assertIsNotNone(Path.Log.error("something")) def test33(self): """Verify log level INFO.""" - PathLog.setLevel(PathLog.Level.INFO) - self.assertIsNone(PathLog.debug("something")) - self.assertIsNotNone(PathLog.info("something")) - self.assertIsNotNone(PathLog.notice("something")) - self.assertIsNotNone(PathLog.warning("something")) - self.assertIsNotNone(PathLog.error("something")) + Path.Log.setLevel(Path.Log.Level.INFO) + self.assertIsNone(Path.Log.debug("something")) + self.assertIsNotNone(Path.Log.info("something")) + self.assertIsNotNone(Path.Log.notice("something")) + self.assertIsNotNone(Path.Log.warning("something")) + self.assertIsNotNone(Path.Log.error("something")) def test34(self): """Verify log level DEBUG.""" - PathLog.setLevel(PathLog.Level.DEBUG) - self.assertIsNotNone(PathLog.debug("something")) - self.assertIsNotNone(PathLog.info("something")) - self.assertIsNotNone(PathLog.notice("something")) - self.assertIsNotNone(PathLog.warning("something")) - self.assertIsNotNone(PathLog.error("something")) + Path.Log.setLevel(Path.Log.Level.DEBUG) + self.assertIsNotNone(Path.Log.debug("something")) + self.assertIsNotNone(Path.Log.info("something")) + self.assertIsNotNone(Path.Log.notice("something")) + self.assertIsNotNone(Path.Log.warning("something")) + self.assertIsNotNone(Path.Log.error("something")) def test50(self): """Verify no tracking by default.""" - self.assertIsNone(PathLog.track("this", "and", "that")) + self.assertIsNone(Path.Log.track("this", "and", "that")) def test51(self): """Verify enabling tracking for module results in tracking.""" - PathLog.trackModule() + Path.Log.trackModule() # Don't want to rely on the line number matching - still want some # indication that track does the right thing .... - msg = PathLog.track("this", "and", "that") + msg = Path.Log.track("this", "and", "that") self.assertTrue(msg.startswith(self.MODULE)) self.assertTrue(msg.endswith("test51(this, and, that)")) def test52(self): """Verify untracking stops tracking.""" - PathLog.trackModule() - self.assertIsNotNone(PathLog.track("this", "and", "that")) - PathLog.untrackModule() - self.assertIsNone(PathLog.track("this", "and", "that")) + Path.Log.trackModule() + self.assertIsNotNone(Path.Log.track("this", "and", "that")) + Path.Log.untrackModule() + self.assertIsNone(Path.Log.track("this", "and", "that")) def test53(self): """Verify trackAllModules works correctly.""" - PathLog.trackAllModules(True) - self.assertIsNotNone(PathLog.track("this", "and", "that")) - PathLog.trackAllModules(False) - self.assertIsNone(PathLog.track("this", "and", "that")) - PathLog.trackAllModules(True) - PathLog.trackModule() - self.assertIsNotNone(PathLog.track("this", "and", "that")) - PathLog.trackAllModules(False) - self.assertIsNotNone(PathLog.track("this", "and", "that")) + Path.Log.trackAllModules(True) + self.assertIsNotNone(Path.Log.track("this", "and", "that")) + Path.Log.trackAllModules(False) + self.assertIsNone(Path.Log.track("this", "and", "that")) + Path.Log.trackAllModules(True) + Path.Log.trackModule() + self.assertIsNotNone(Path.Log.track("this", "and", "that")) + Path.Log.trackAllModules(False) + self.assertIsNotNone(Path.Log.track("this", "and", "that")) def test60(self): """Verify track handles no argument.""" - PathLog.trackModule() - msg = PathLog.track() + Path.Log.trackModule() + msg = Path.Log.track() self.assertTrue(msg.startswith(self.MODULE)) self.assertTrue(msg.endswith("test60()")) def test61(self): """Verify track handles arbitrary argument types correctly.""" - PathLog.trackModule() - msg = PathLog.track("this", None, 1, 18.25) + Path.Log.trackModule() + msg = Path.Log.track("this", None, 1, 18.25) self.assertTrue(msg.startswith(self.MODULE)) self.assertTrue(msg.endswith("test61(this, None, 1, 18.25)")) def testzz(self): """Restoring environment after tests.""" - PathLog.setLevel(PathLog.Level.RESET) + Path.Log.setLevel(Path.Log.Level.RESET) diff --git a/src/Mod/Path/PathTests/TestPathOpTools.py b/src/Mod/Path/PathTests/TestPathOpUtil.py similarity index 80% rename from src/Mod/Path/PathTests/TestPathOpTools.py rename to src/Mod/Path/PathTests/TestPathOpUtil.py index 34dfc09c5a..c066352745 100644 --- a/src/Mod/Path/PathTests/TestPathOpTools.py +++ b/src/Mod/Path/PathTests/TestPathOpUtil.py @@ -22,16 +22,15 @@ import FreeCAD import Part -import PathScripts.PathGeom as PathGeom -import PathScripts.PathOpTools as PathOpTools -import PathScripts.PathLog as PathLog +import Path +import Path.Op.Util as PathOpUtil import PathTests.PathTestUtils as PathTestUtils import math from FreeCAD import Vector -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +# Path.Log.trackModule(Path.Log.thisModule()) def getWire(obj, nr=0): @@ -85,7 +84,7 @@ def wireMarkers(wire): return pts -class TestPathOpTools(PathTestUtils.PathTestBase): +class TestPathOpUtil(PathTestUtils.PathTestBase): @classmethod def setUpClass(cls): global doc @@ -104,18 +103,18 @@ class TestPathOpTools(PathTestUtils.PathTestBase): pc = Vector(5, 5, 0) pd = Vector(5, 1, 0) - self.assertTrue(PathOpTools.isWireClockwise(makeWire([pa, pb, pc, pd]))) - self.assertFalse(PathOpTools.isWireClockwise(makeWire([pa, pd, pc, pb]))) + self.assertTrue(PathOpUtil.isWireClockwise(makeWire([pa, pb, pc, pd]))) + self.assertFalse(PathOpUtil.isWireClockwise(makeWire([pa, pd, pc, pb]))) def test01(self): """Verify isWireClockwise for single edge circle wires.""" self.assertTrue( - PathOpTools.isWireClockwise( + PathOpUtil.isWireClockwise( Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1)) ) ) self.assertFalse( - PathOpTools.isWireClockwise( + PathOpUtil.isWireClockwise( Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1)) ) ) @@ -124,31 +123,31 @@ class TestPathOpTools(PathTestUtils.PathTestBase): """Verify isWireClockwise for two half circle wires.""" e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1), 0, 180) e1 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1), 180, 360) - self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e1]))) + self.assertTrue(PathOpUtil.isWireClockwise(Part.Wire([e0, e1]))) e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1), 0, 180) e1 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1), 180, 360) - self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e1]))) + self.assertFalse(PathOpUtil.isWireClockwise(Part.Wire([e0, e1]))) def test03(self): """Verify isWireClockwise for two edge wires with an arc.""" e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1), 0, 180) e2 = Part.makeLine(e0.valueAt(e0.LastParameter), e0.valueAt(e0.FirstParameter)) - self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e2]))) + self.assertTrue(PathOpUtil.isWireClockwise(Part.Wire([e0, e2]))) e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1), 0, 180) e2 = Part.makeLine(e0.valueAt(e0.LastParameter), e0.valueAt(e0.FirstParameter)) - self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e2]))) + self.assertFalse(PathOpUtil.isWireClockwise(Part.Wire([e0, e2]))) def test04(self): """Verify isWireClockwise for unoriented wires.""" e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1), 0, 180) e3 = Part.makeLine(e0.valueAt(e0.FirstParameter), e0.valueAt(e0.LastParameter)) - self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e3]))) + self.assertTrue(PathOpUtil.isWireClockwise(Part.Wire([e0, e3]))) e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1), 0, 180) e3 = Part.makeLine(e0.valueAt(e0.FirstParameter), e0.valueAt(e0.LastParameter)) - self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e3]))) + self.assertFalse(PathOpUtil.isWireClockwise(Part.Wire([e0, e3]))) def test11(self): """Check offsetting a circular hole.""" @@ -157,13 +156,13 @@ class TestPathOpTools(PathTestUtils.PathTestBase): small = getWireInside(obj) self.assertRoughly(10, small.Edges[0].Curve.Radius) - wire = PathOpTools.offsetWire(small, obj.Shape, 3, True) + wire = PathOpUtil.offsetWire(small, obj.Shape, 3, True) self.assertIsNotNone(wire) self.assertEqual(1, len(wire.Edges)) self.assertRoughly(7, wire.Edges[0].Curve.Radius) self.assertCoincide(Vector(0, 0, 1), wire.Edges[0].Curve.Axis) - wire = PathOpTools.offsetWire(small, obj.Shape, 9.9, True) + wire = PathOpUtil.offsetWire(small, obj.Shape, 9.9, True) self.assertIsNotNone(wire) self.assertEqual(1, len(wire.Edges)) self.assertRoughly(0.1, wire.Edges[0].Curve.Radius) @@ -175,10 +174,10 @@ class TestPathOpTools(PathTestUtils.PathTestBase): small = getWireInside(obj) self.assertRoughly(10, small.Edges[0].Curve.Radius) - wire = PathOpTools.offsetWire(small, obj.Shape, 10, True) + wire = PathOpUtil.offsetWire(small, obj.Shape, 10, True) self.assertIsNone(wire) - wire = PathOpTools.offsetWire(small, obj.Shape, 15, True) + wire = PathOpUtil.offsetWire(small, obj.Shape, 15, True) self.assertIsNone(wire) def test13(self): @@ -188,13 +187,13 @@ class TestPathOpTools(PathTestUtils.PathTestBase): big = getWireOutside(obj) self.assertRoughly(20, big.Edges[0].Curve.Radius) - wire = PathOpTools.offsetWire(big, obj.Shape, 10, True) + wire = PathOpUtil.offsetWire(big, obj.Shape, 10, True) self.assertIsNotNone(wire) self.assertEqual(1, len(wire.Edges)) self.assertRoughly(30, wire.Edges[0].Curve.Radius) self.assertCoincide(Vector(0, 0, -1), wire.Edges[0].Curve.Axis) - wire = PathOpTools.offsetWire(big, obj.Shape, 20, True) + wire = PathOpUtil.offsetWire(big, obj.Shape, 20, True) self.assertIsNotNone(wire) self.assertEqual(1, len(wire.Edges)) self.assertRoughly(40, wire.Edges[0].Curve.Radius) @@ -208,16 +207,16 @@ class TestPathOpTools(PathTestUtils.PathTestBase): w for w in obj.Shape.Wires if 1 == len(w.Edges) - and PathGeom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) + and Path.Geom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) ] self.assertEqual(2, len(wires)) w = wires[1] if wires[0].BoundBox.isInside(wires[1].BoundBox) else wires[0] self.assertRoughly(10, w.Edges[0].Curve.Radius) # make sure there is a placement and I didn't mess up the model - self.assertFalse(PathGeom.pointsCoincide(Vector(), w.Edges[0].Placement.Base)) + self.assertFalse(Path.Geom.pointsCoincide(Vector(), w.Edges[0].Placement.Base)) - wire = PathOpTools.offsetWire(w, obj.Shape, 2, True) + wire = PathOpUtil.offsetWire(w, obj.Shape, 2, True) self.assertIsNotNone(wire) self.assertEqual(1, len(wire.Edges)) self.assertRoughly(8, wire.Edges[0].Curve.Radius) @@ -232,16 +231,16 @@ class TestPathOpTools(PathTestUtils.PathTestBase): w for w in obj.Shape.Wires if 1 == len(w.Edges) - and PathGeom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) + and Path.Geom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) ] self.assertEqual(2, len(wires)) w = wires[0] if wires[0].BoundBox.isInside(wires[1].BoundBox) else wires[1] self.assertRoughly(20, w.Edges[0].Curve.Radius) # make sure there is a placement and I didn't mess up the model - self.assertFalse(PathGeom.pointsCoincide(Vector(), w.Edges[0].Placement.Base)) + self.assertFalse(Path.Geom.pointsCoincide(Vector(), w.Edges[0].Placement.Base)) - wire = PathOpTools.offsetWire(w, obj.Shape, 2, True) + wire = PathOpUtil.offsetWire(w, obj.Shape, 2, True) self.assertIsNotNone(wire) self.assertEqual(1, len(wire.Edges)) self.assertRoughly(22, wire.Edges[0].Curve.Radius) @@ -267,12 +266,12 @@ class TestPathOpTools(PathTestUtils.PathTestBase): ], ) - wire = PathOpTools.offsetWire(small, obj.Shape, 3, True) + wire = PathOpUtil.offsetWire(small, obj.Shape, 3, True) self.assertIsNotNone(wire) self.assertEqual(3, len(wire.Edges)) self.assertTrue(wire.isClosed()) # for holes processing "forward" means CCW - self.assertFalse(PathOpTools.isWireClockwise(wire)) + self.assertFalse(PathOpUtil.isWireClockwise(wire)) y = 4 # offset works in both directions x = 4 * math.cos(math.pi / 6) self.assertLines( @@ -299,7 +298,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): Vector(0, y, 0), ], ) - wire = PathOpTools.offsetWire(small, obj.Shape, 5, True) + wire = PathOpUtil.offsetWire(small, obj.Shape, 5, True) self.assertIsNone(wire) def test22(self): @@ -321,7 +320,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): ], ) - wire = PathOpTools.offsetWire(big, obj.Shape, 5, True) + wire = PathOpUtil.offsetWire(big, obj.Shape, 5, True) self.assertIsNotNone(wire) self.assertEqual(6, len(wire.Edges)) lastAngle = None @@ -335,28 +334,28 @@ class TestPathOpTools(PathTestUtils.PathTestBase): begin = e.Vertexes[0].Point end = e.Vertexes[1].Point v = end - begin - angle = PathGeom.getAngle(v) - if PathGeom.isRoughly(0, angle) or PathGeom.isRoughly( + angle = Path.Geom.getAngle(v) + if Path.Geom.isRoughly(0, angle) or Path.Geom.isRoughly( math.pi, math.fabs(angle) ): if lastAngle: self.assertRoughly(-refAngle, lastAngle) - elif PathGeom.isRoughly(+refAngle, angle): + elif Path.Geom.isRoughly(+refAngle, angle): if lastAngle: self.assertRoughly(math.pi, math.fabs(lastAngle)) - elif PathGeom.isRoughly(-refAngle, angle): + elif Path.Geom.isRoughly(-refAngle, angle): if lastAngle: self.assertRoughly(+refAngle, lastAngle) else: self.assertIsNone("%s: angle=%s" % (type(e.Curve), angle)) lastAngle = angle - self.assertTrue(PathOpTools.isWireClockwise(wire)) + self.assertTrue(PathOpUtil.isWireClockwise(wire)) def test31(self): """Check offsetting a cylinder.""" obj = doc.getObjectsByLabel("circle-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) self.assertEqual(1, len(wire.Edges)) edge = wire.Edges[0] self.assertCoincide(Vector(), edge.Curve.Center) @@ -364,7 +363,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertRoughly(33, edge.Curve.Radius) # the other way around everything's the same except the axis is negative - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getPositiveShape(obj), 3, False ) self.assertEqual(1, len(wire.Edges)) @@ -377,7 +376,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): """Check offsetting a box.""" obj = doc.getObjectsByLabel("square-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) self.assertEqual(8, len(wire.Edges)) self.assertEqual(4, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) self.assertEqual( @@ -385,17 +384,17 @@ class TestPathOpTools(PathTestUtils.PathTestBase): ) for e in wire.Edges: if Part.Line == type(e.Curve): - if PathGeom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): + if Path.Geom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): self.assertEqual(40, e.Length) - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): self.assertEqual(60, e.Length) if Part.Circle == type(e.Curve): self.assertRoughly(3, e.Curve.Radius) self.assertCoincide(Vector(0, 0, -1), e.Curve.Axis) - self.assertTrue(PathOpTools.isWireClockwise(wire)) + self.assertTrue(PathOpUtil.isWireClockwise(wire)) # change offset orientation - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getPositiveShape(obj), 3, False ) self.assertEqual(8, len(wire.Edges)) @@ -405,20 +404,20 @@ class TestPathOpTools(PathTestUtils.PathTestBase): ) for e in wire.Edges: if Part.Line == type(e.Curve): - if PathGeom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): + if Path.Geom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): self.assertEqual(40, e.Length) - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): self.assertEqual(60, e.Length) if Part.Circle == type(e.Curve): self.assertRoughly(3, e.Curve.Radius) self.assertCoincide(Vector(0, 0, +1), e.Curve.Axis) - self.assertFalse(PathOpTools.isWireClockwise(wire)) + self.assertFalse(PathOpUtil.isWireClockwise(wire)) def test33(self): """Check offsetting a triangle.""" obj = doc.getObjectsByLabel("triangle-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) self.assertEqual( @@ -433,7 +432,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(0, 0, -1), e.Curve.Axis) # change offset orientation - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getPositiveShape(obj), 3, False ) self.assertEqual(6, len(wire.Edges)) @@ -452,7 +451,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): """Check offsetting a shape.""" obj = doc.getObjectsByLabel("shape-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) self.assertEqual( @@ -468,7 +467,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(0, 0, -1), e.Curve.Axis) # change offset orientation - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getPositiveShape(obj), 3, False ) self.assertEqual(6, len(wire.Edges)) @@ -487,7 +486,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): """Check offsetting a cylindrical hole.""" obj = doc.getObjectsByLabel("circle-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) self.assertEqual(1, len(wire.Edges)) edge = wire.Edges[0] self.assertCoincide(Vector(), edge.Curve.Center) @@ -495,7 +494,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertRoughly(27, edge.Curve.Radius) # the other way around everything's the same except the axis is negative - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getNegativeShape(obj), 3, False ) self.assertEqual(1, len(wire.Edges)) @@ -508,56 +507,56 @@ class TestPathOpTools(PathTestUtils.PathTestBase): """Check offsetting a square hole.""" obj = doc.getObjectsByLabel("square-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) self.assertEqual(4, len(wire.Edges)) self.assertEqual(4, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) for e in wire.Edges: - if PathGeom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): + if Path.Geom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): self.assertRoughly(34, e.Length) - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): self.assertRoughly(54, e.Length) - self.assertFalse(PathOpTools.isWireClockwise(wire)) + self.assertFalse(PathOpUtil.isWireClockwise(wire)) # change offset orientation - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getNegativeShape(obj), 3, False ) self.assertEqual(4, len(wire.Edges)) self.assertEqual(4, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) for e in wire.Edges: - if PathGeom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): + if Path.Geom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): self.assertRoughly(34, e.Length) - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y): self.assertRoughly(54, e.Length) - self.assertTrue(PathOpTools.isWireClockwise(wire)) + self.assertTrue(PathOpUtil.isWireClockwise(wire)) def test37(self): """Check offsetting a triangular holee.""" obj = doc.getObjectsByLabel("triangle-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) self.assertEqual(3, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) length = 48 * math.sin(math.radians(60)) for e in wire.Edges: self.assertRoughly(length, e.Length) - self.assertFalse(PathOpTools.isWireClockwise(wire)) + self.assertFalse(PathOpUtil.isWireClockwise(wire)) # change offset orientation - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getNegativeShape(obj), 3, False ) self.assertEqual(3, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) for e in wire.Edges: self.assertRoughly(length, e.Length) - self.assertTrue(PathOpTools.isWireClockwise(wire)) + self.assertTrue(PathOpUtil.isWireClockwise(wire)) def test38(self): """Check offsetting a shape hole.""" obj = doc.getObjectsByLabel("shape-cut")[0] - wire = PathOpTools.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) + wire = PathOpUtil.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) self.assertEqual( @@ -573,7 +572,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(0, 0, +1), e.Curve.Axis) # change offset orientation - wire = PathOpTools.offsetWire( + wire = PathOpUtil.offsetWire( getWire(obj.Tool), getNegativeShape(obj), 3, False ) self.assertEqual(6, len(wire.Edges)) @@ -601,7 +600,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): hEdges = [ e for e in w.Edges - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 @@ -612,7 +611,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(-x, y, 0), edge.Vertexes[0].Point) self.assertCoincide(Vector(+x, y, 0), edge.Vertexes[1].Point) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 5, True) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 5, True) self.assertEqual(1, len(wire.Edges)) y = y - 5 @@ -620,8 +619,8 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(-x, y, 0), wire.Edges[0].Vertexes[1].Point) # make sure we get the same result even if the edge is oriented the other way - edge = PathGeom.flipEdge(edge) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 5, True) + edge = Path.Geom.flipEdge(edge) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 5, True) self.assertEqual(1, len(wire.Edges)) self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[0].Point) @@ -640,7 +639,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): hEdges = [ e for e in w.Edges - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 @@ -650,7 +649,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(-x, y, 0), edge.Vertexes[0].Point) self.assertCoincide(Vector(+x, y, 0), edge.Vertexes[1].Point) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 5, False) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 5, False) self.assertEqual(1, len(wire.Edges)) y = y - 5 @@ -658,8 +657,8 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[1].Point) # make sure we get the same result on a reversed edge - edge = PathGeom.flipEdge(edge) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 5, False) + edge = Path.Geom.flipEdge(edge) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 5, False) self.assertEqual(1, len(wire.Edges)) self.assertCoincide(Vector(-x, y, 0), wire.Edges[0].Vertexes[0].Point) @@ -678,11 +677,11 @@ class TestPathOpTools(PathTestUtils.PathTestBase): lEdges = [ e for e in w.Edges - if not PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if not Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] self.assertEqual(2, len(lEdges)) - wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, True) + wire = PathOpUtil.offsetWire(Part.Wire(lEdges), obj.Shape, 2, True) x = length / 2 + 2 * math.cos(math.pi / 6) y = -10 + 2 * math.sin(math.pi / 6) @@ -697,7 +696,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(0, 0, -1), rEdges[0].Curve.Axis) # offset the other way - wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) + wire = PathOpUtil.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[0].Point) self.assertCoincide(Vector(-x, y, 0), wire.Edges[-1].Vertexes[1].Point) @@ -721,12 +720,12 @@ class TestPathOpTools(PathTestUtils.PathTestBase): lEdges = [ e for e in w.Edges - if not PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if not Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] self.assertEqual(2, len(lEdges)) - w = PathGeom.flipWire(Part.Wire(lEdges)) - wire = PathOpTools.offsetWire(w, obj.Shape, 2, True) + w = Path.Geom.flipWire(Part.Wire(lEdges)) + wire = PathOpUtil.offsetWire(w, obj.Shape, 2, True) x = length / 2 + 2 * math.cos(math.pi / 6) y = -10 + 2 * math.sin(math.pi / 6) @@ -741,7 +740,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(0, 0, -1), rEdges[0].Curve.Axis) # offset the other way - wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) + wire = PathOpUtil.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[0].Point) self.assertCoincide(Vector(-x, y, 0), wire.Edges[-1].Vertexes[1].Point) @@ -765,7 +764,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): hEdges = [ e for e in w.Edges - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 @@ -776,7 +775,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(-x, y, 0), edge.Vertexes[0].Point) self.assertCoincide(Vector(+x, y, 0), edge.Vertexes[1].Point) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 2, True) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 2, True) self.assertEqual(1, len(wire.Edges)) y = y + 2 @@ -784,8 +783,8 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[1].Point) # make sure we get the same result even if the edge is oriented the other way - edge = PathGeom.flipEdge(edge) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 2, True) + edge = Path.Geom.flipEdge(edge) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 2, True) self.assertEqual(1, len(wire.Edges)) self.assertCoincide(Vector(-x, y, 0), wire.Edges[0].Vertexes[0].Point) @@ -804,7 +803,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): hEdges = [ e for e in w.Edges - if PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 @@ -815,7 +814,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(-x, y, 0), edge.Vertexes[0].Point) self.assertCoincide(Vector(+x, y, 0), edge.Vertexes[1].Point) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 2, False) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 2, False) self.assertEqual(1, len(wire.Edges)) y = y + 2 @@ -823,8 +822,8 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertCoincide(Vector(-x, y, 0), wire.Edges[0].Vertexes[1].Point) # make sure we get the same result even if the edge is oriented the other way - edge = PathGeom.flipEdge(edge) - wire = PathOpTools.offsetWire(Part.Wire([edge]), obj.Shape, 2, False) + edge = Path.Geom.flipEdge(edge) + wire = PathOpUtil.offsetWire(Part.Wire([edge]), obj.Shape, 2, False) self.assertEqual(1, len(wire.Edges)) self.assertCoincide(Vector(+x, y, 0), wire.Edges[0].Vertexes[0].Point) @@ -841,11 +840,11 @@ class TestPathOpTools(PathTestUtils.PathTestBase): lEdges = [ e for e in w.Edges - if not PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if not Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] self.assertEqual(2, len(lEdges)) - wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, True) + wire = PathOpUtil.offsetWire(Part.Wire(lEdges), obj.Shape, 2, True) x = length / 2 - 2 * math.cos(math.pi / 6) y = -5 - 2 * math.sin(math.pi / 6) @@ -857,7 +856,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertEqual(0, len(rEdges)) # offset the other way - wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) + wire = PathOpUtil.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) self.assertCoincide(Vector(-x, y, 0), wire.Edges[0].Vertexes[0].Point) self.assertCoincide(Vector(+x, y, 0), wire.Edges[-1].Vertexes[1].Point) @@ -878,12 +877,12 @@ class TestPathOpTools(PathTestUtils.PathTestBase): lEdges = [ e for e in w.Edges - if not PathGeom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + if not Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] self.assertEqual(2, len(lEdges)) - w = PathGeom.flipWire(Part.Wire(lEdges)) - wire = PathOpTools.offsetWire(w, obj.Shape, 2, True) + w = Path.Geom.flipWire(Part.Wire(lEdges)) + wire = PathOpUtil.offsetWire(w, obj.Shape, 2, True) x = length / 2 - 2 * math.cos(math.pi / 6) y = -5 - 2 * math.sin(math.pi / 6) @@ -895,7 +894,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): self.assertEqual(0, len(rEdges)) # offset the other way - wire = PathOpTools.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) + wire = PathOpUtil.offsetWire(Part.Wire(lEdges), obj.Shape, 2, False) self.assertCoincide(Vector(-x, y, 0), wire.Edges[0].Vertexes[0].Point) self.assertCoincide(Vector(+x, y, 0), wire.Edges[-1].Vertexes[1].Point) @@ -913,7 +912,7 @@ class TestPathOpTools(PathTestUtils.PathTestBase): e0 = Part.Edge(Part.LineSegment(p0, p1)) e1 = Part.Edge(Part.LineSegment(p1, p2)) - wire = PathOpTools.orientWire(Part.Wire([e0, e1])) + wire = PathOpUtil.orientWire(Part.Wire([e0, e1])) wirePts = wireMarkers(wire) self.assertPointsMatch(wirePts, pts) @@ -930,16 +929,16 @@ class TestPathOpTools(PathTestUtils.PathTestBase): e1p = Part.Edge(Part.LineSegment(p1, p2)) e1m = Part.Edge(Part.LineSegment(p2, p1)) - wire = PathOpTools.orientWire(Part.Wire([e0p, e1p])) + wire = PathOpUtil.orientWire(Part.Wire([e0p, e1p])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0p, e1m])) + wire = PathOpUtil.orientWire(Part.Wire([e0p, e1m])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0m, e1p])) + wire = PathOpUtil.orientWire(Part.Wire([e0m, e1p])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0m, e1m])) + wire = PathOpUtil.orientWire(Part.Wire([e0m, e1m])) self.assertPointsMatch(wireMarkers(wire), pts) def test52(self): @@ -957,26 +956,26 @@ class TestPathOpTools(PathTestUtils.PathTestBase): e2p = Part.Edge(Part.LineSegment(p2, p3)) e2m = Part.Edge(Part.LineSegment(p3, p2)) - wire = PathOpTools.orientWire(Part.Wire([e0p, e1p, e2p])) + wire = PathOpUtil.orientWire(Part.Wire([e0p, e1p, e2p])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0p, e1m, e2p])) + wire = PathOpUtil.orientWire(Part.Wire([e0p, e1m, e2p])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0m, e1p, e2p])) + wire = PathOpUtil.orientWire(Part.Wire([e0m, e1p, e2p])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0m, e1m, e2p])) + wire = PathOpUtil.orientWire(Part.Wire([e0m, e1m, e2p])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0p, e1p, e2m])) + wire = PathOpUtil.orientWire(Part.Wire([e0p, e1p, e2m])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0p, e1m, e2m])) + wire = PathOpUtil.orientWire(Part.Wire([e0p, e1m, e2m])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0m, e1p, e2m])) + wire = PathOpUtil.orientWire(Part.Wire([e0m, e1p, e2m])) self.assertPointsMatch(wireMarkers(wire), pts) - wire = PathOpTools.orientWire(Part.Wire([e0m, e1m, e2m])) + wire = PathOpUtil.orientWire(Part.Wire([e0m, e1m, e2m])) self.assertPointsMatch(wireMarkers(wire), pts) diff --git a/src/Mod/Path/PathTests/TestPathPost.py b/src/Mod/Path/PathTests/TestPathPost.py index 3d980fc778..55240d00c1 100644 --- a/src/Mod/Path/PathTests/TestPathPost.py +++ b/src/Mod/Path/PathTests/TestPathPost.py @@ -28,20 +28,18 @@ import unittest import FreeCAD import Path -from PathScripts import PathLog -from PathScripts import PathPost -from PathScripts import PathPreferences -from PathScripts import PostUtils +import Path.Post.Command as PathPost +import Path.Post.Utils as PostUtils -from PathScripts.PathPostProcessor import PostProcessor +import Path.Post.Processor as PostProcessor # If KEEP_DEBUG_OUTPUT is False, remove the gcode file after the test succeeds. # If KEEP_DEBUG_OUTPUT is True or the test fails leave the gcode file behind # so it can be looked at easily. KEEP_DEBUG_OUTPUT = False -PathPost.LOG_MODULE = PathLog.thisModule() -PathLog.setLevel(PathLog.Level.INFO, PathPost.LOG_MODULE) +PathPost.LOG_MODULE = Path.Log.thisModule() +Path.Log.setLevel(Path.Log.Level.INFO, PathPost.LOG_MODULE) class TestPathPost(unittest.TestCase): @@ -410,7 +408,7 @@ class TestOutputNameSubstitution(unittest.TestCase): FreeCAD.setActiveDocument(self.doc.Label) teststring = "" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) self.job.SplitOutput = False @@ -426,7 +424,7 @@ class TestOutputNameSubstitution(unittest.TestCase): # Test basic string substitution without splitting teststring = "~/Desktop/%j.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) self.job.SplitOutput = False @@ -444,7 +442,7 @@ class TestOutputNameSubstitution(unittest.TestCase): # Substitute current file path teststring = "%D/testfile.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) outlist = PathPost.buildPostList(self.job) @@ -458,7 +456,7 @@ class TestOutputNameSubstitution(unittest.TestCase): def test020(self): teststring = "%d.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) outlist = PathPost.buildPostList(self.job) @@ -469,7 +467,7 @@ class TestOutputNameSubstitution(unittest.TestCase): def test030(self): teststring = "%M/outfile.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) outlist = PathPost.buildPostList(self.job) @@ -481,7 +479,7 @@ class TestOutputNameSubstitution(unittest.TestCase): # unused substitution strings should be ignored teststring = "%d%T%t%W%O/testdoc.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) outlist = PathPost.buildPostList(self.job) @@ -496,7 +494,7 @@ class TestOutputNameSubstitution(unittest.TestCase): # explicitly using the sequence number should include it where indicated. teststring = "%S-%d.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) outlist = PathPost.buildPostList(self.job) @@ -513,7 +511,7 @@ class TestOutputNameSubstitution(unittest.TestCase): # substitute jobname and use default sequence numbers teststring = "%j.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) subpart, objs = outlist[0] @@ -526,7 +524,7 @@ class TestOutputNameSubstitution(unittest.TestCase): # Use Toolnumbers and default sequence numbers teststring = "%T.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) outlist = PathPost.buildPostList(self.job) @@ -540,7 +538,7 @@ class TestOutputNameSubstitution(unittest.TestCase): # Use Tooldescriptions and default sequence numbers teststring = "%t.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) outlist = PathPost.buildPostList(self.job) @@ -559,7 +557,7 @@ class TestOutputNameSubstitution(unittest.TestCase): teststring = "%j.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) subpart, objs = outlist[0] @@ -571,7 +569,7 @@ class TestOutputNameSubstitution(unittest.TestCase): teststring = "%W-%j.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) subpart, objs = outlist[0] @@ -589,7 +587,7 @@ class TestOutputNameSubstitution(unittest.TestCase): teststring = "%j.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) subpart, objs = outlist[0] @@ -601,7 +599,7 @@ class TestOutputNameSubstitution(unittest.TestCase): teststring = "%O-%j.nc" self.job.PostProcessorOutputFile = teststring - PathPreferences.setOutputFileDefaults( + Path.Preferences.setOutputFileDefaults( teststring, "Append Unique ID on conflict" ) subpart, objs = outlist[0] diff --git a/src/Mod/Path/PathTests/TestPathPreferences.py b/src/Mod/Path/PathTests/TestPathPreferences.py index 589c6ee64b..0febdf5b35 100644 --- a/src/Mod/Path/PathTests/TestPathPreferences.py +++ b/src/Mod/Path/PathTests/TestPathPreferences.py @@ -20,7 +20,7 @@ # * * # *************************************************************************** -import PathScripts.PathPreferences as PathPreferences +import Path import PathTests.PathTestUtils as PathTestUtils @@ -28,22 +28,22 @@ class TestPathPreferences(PathTestUtils.PathTestBase): def test00(self): """There is at least one search path.""" - paths = PathPreferences.searchPaths() + paths = Path.Preferences.searchPaths() self.assertGreater(len(paths), 0) def test01(self): - """PathScripts is part of the posts search path.""" - paths = PathPreferences.searchPathsPost() - self.assertEqual(len([p for p in paths if p.endswith("/PathScripts/")]), 1) + """Path/Post is part of the posts search path.""" + paths = Path.Preferences.searchPathsPost() + self.assertEqual(len([p for p in paths if p.endswith("/Path/Post/")]), 1) def test02(self): - """PathScripts/post is part of the posts search path.""" - paths = PathPreferences.searchPathsPost() - self.assertEqual(len([p for p in paths if p.endswith("/PathScripts/post/")]), 1) + """Path/Post/scripts is part of the posts search path.""" + paths = Path.Preferences.searchPathsPost() + self.assertEqual(len([p for p in paths if p.endswith("/Path/Post/scripts/")]), 1) def test03(self): """Available post processors include linuxcnc, grbl and opensbp.""" - posts = PathPreferences.allAvailablePostProcessors() + posts = Path.Preferences.allAvailablePostProcessors() self.assertTrue("linuxcnc" in posts) self.assertTrue("grbl" in posts) self.assertTrue("opensbp" in posts) @@ -51,17 +51,17 @@ class TestPathPreferences(PathTestUtils.PathTestBase): def test10(self): """Default paths for tools are resolved correctly""" - self.assertTrue(PathPreferences.pathDefaultToolsPath().endswith("/Path/Tools/")) + self.assertTrue(Path.Preferences.pathDefaultToolsPath().endswith("/Path/Tools/")) self.assertTrue( - PathPreferences.pathDefaultToolsPath("Bit").endswith("/Path/Tools/Bit") + Path.Preferences.pathDefaultToolsPath("Bit").endswith("/Path/Tools/Bit") ) self.assertTrue( - PathPreferences.pathDefaultToolsPath("Library").endswith( + Path.Preferences.pathDefaultToolsPath("Library").endswith( "/Path/Tools/Library" ) ) self.assertTrue( - PathPreferences.pathDefaultToolsPath("Template").endswith( + Path.Preferences.pathDefaultToolsPath("Template").endswith( "/Path/Tools/Template" ) ) diff --git a/src/Mod/Path/PathTests/TestPathPropertyBag.py b/src/Mod/Path/PathTests/TestPathPropertyBag.py index 71019dfb27..ae675b71ff 100644 --- a/src/Mod/Path/PathTests/TestPathPropertyBag.py +++ b/src/Mod/Path/PathTests/TestPathPropertyBag.py @@ -21,7 +21,7 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathPropertyBag as PathPropertyBag +import Path.Base.PropertyBag as PathPropertyBag import PathTests.PathTestUtils as PathTestUtils diff --git a/src/Mod/Path/PathTests/TestPathRotationGenerator.py b/src/Mod/Path/PathTests/TestPathRotationGenerator.py index c9a3065d58..78f6dbb0ad 100644 --- a/src/Mod/Path/PathTests/TestPathRotationGenerator.py +++ b/src/Mod/Path/PathTests/TestPathRotationGenerator.py @@ -20,15 +20,14 @@ # * * # *************************************************************************** -import Path import FreeCAD -import Generators.rotation_generator as generator -import PathScripts.PathLog as PathLog +import Path +import Path.Base.Generator.rotation as generator import PathTests.PathTestUtils as PathTestUtils import numpy as np -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestPathRotationGenerator(PathTestUtils.PathTestBase): @@ -75,7 +74,7 @@ class TestPathRotationGenerator(PathTestUtils.PathTestBase): result = generator.generate(**args) self.assertTrue(len(result) == 2) - PathLog.debug(result) + Path.Log.debug(result) def test20(self): """Test non-zero rotation""" @@ -92,11 +91,11 @@ class TestPathRotationGenerator(PathTestUtils.PathTestBase): result = generator.generate(**args) command = result[0] - PathLog.debug(command.Parameters) + Path.Log.debug(command.Parameters) self.assertTrue(np.isclose(command.Parameters["A"], 54.736)) self.assertTrue(np.isclose(command.Parameters["C"], 45)) - PathLog.track(result) + Path.Log.track(result) def test30(self): """Test A limits""" @@ -109,7 +108,7 @@ class TestPathRotationGenerator(PathTestUtils.PathTestBase): args["aMax"] = 0 result = generator.generate(**args) - PathLog.debug(result) + Path.Log.debug(result) command = result[0] self.assertTrue(np.isclose(command.Parameters["A"], -54.736)) @@ -120,7 +119,7 @@ class TestPathRotationGenerator(PathTestUtils.PathTestBase): args["aMax"] = 90 result = generator.generate(**args) - PathLog.debug(result) + Path.Log.debug(result) command = result[0] self.assertTrue(np.isclose(command.Parameters["A"], 54.736)) @@ -137,7 +136,7 @@ class TestPathRotationGenerator(PathTestUtils.PathTestBase): args["cMax"] = 0 result = generator.generate(**args) - PathLog.debug(result) + Path.Log.debug(result) command = result[0] self.assertTrue(np.isclose(command.Parameters["A"], -54.736)) @@ -148,7 +147,7 @@ class TestPathRotationGenerator(PathTestUtils.PathTestBase): args["cMax"] = 180 result = generator.generate(**args) - PathLog.debug(result) + Path.Log.debug(result) command = result[0] self.assertTrue(np.isclose(command.Parameters["A"], 54.736)) diff --git a/src/Mod/Path/PathTests/TestPathSetupSheet.py b/src/Mod/Path/PathTests/TestPathSetupSheet.py index 9b63124984..9bc25b0589 100644 --- a/src/Mod/Path/PathTests/TestPathSetupSheet.py +++ b/src/Mod/Path/PathTests/TestPathSetupSheet.py @@ -21,13 +21,12 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathSetupSheet as PathSetupSheet -import PathScripts.PathLog as PathLog +import Path +import Path.Base.SetupSheet as PathSetupSheet import json import sys -#PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -#PathLog.trackModule(PathLog.thisModule()) +#Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) from PathTests.PathTestUtils import PathTestBase @@ -37,7 +36,7 @@ def refstring(string): class SomeOp (object): def __init__(self, obj): - PathLog.track(obj, type(obj)) + Path.Log.track(obj, type(obj)) obj.addProperty('App::PropertyPercent', 'StepOver', 'Base', 'Some help you are') @classmethod @@ -46,7 +45,7 @@ class SomeOp (object): @classmethod def Create(cls, name, obj=None, parentJob=None): - PathLog.track(name, obj) + Path.Log.track(name, obj) if obj is None: obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) obj.Proxy = SomeOp(obj) diff --git a/src/Mod/Path/PathTests/TestPathStock.py b/src/Mod/Path/PathTests/TestPathStock.py index e7293e9092..bc2ab0060c 100644 --- a/src/Mod/Path/PathTests/TestPathStock.py +++ b/src/Mod/Path/PathTests/TestPathStock.py @@ -21,7 +21,7 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathStock as PathStock +import Path.Main.Stock as PathStock from PathTests.PathTestUtils import PathTestBase diff --git a/src/Mod/Path/PathTests/TestPathThreadMilling.py b/src/Mod/Path/PathTests/TestPathThreadMilling.py index dac113a77b..a1a29dde92 100644 --- a/src/Mod/Path/PathTests/TestPathThreadMilling.py +++ b/src/Mod/Path/PathTests/TestPathThreadMilling.py @@ -21,8 +21,8 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathGeom as PathGeom -import PathScripts.PathThreadMilling as PathThreadMilling +import Path +import Path.Op.ThreadMilling as PathThreadMilling import math from PathTests.PathTestUtils import PathTestBase diff --git a/src/Mod/Path/PathTests/TestPathThreadMillingGenerator.py b/src/Mod/Path/PathTests/TestPathThreadMillingGenerator.py index c73e5ea592..cfc3ad7ca9 100644 --- a/src/Mod/Path/PathTests/TestPathThreadMillingGenerator.py +++ b/src/Mod/Path/PathTests/TestPathThreadMillingGenerator.py @@ -21,8 +21,7 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathGeom as PathGeom -import Generators.threadmilling_generator as threadmilling +import Path.Base.Generator.threadmilling as threadmilling import math from PathTests.PathTestUtils import PathTestBase diff --git a/src/Mod/Path/PathTests/TestPathTool.py b/src/Mod/Path/PathTests/TestPathTool.py deleted file mode 100644 index 130f16e473..0000000000 --- a/src/Mod/Path/PathTests/TestPathTool.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2017 sliptonic * -# * * -# * 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 Path - -from PathTests.PathTestUtils import PathTestBase - - -class TestPathTool(PathTestBase): - def test00(self): - """Verify templateAttrs""" - - name = "tool 1" - mat = "Carbide" - typ = "EndMill" - dia = 1.7 - flat = 7.2 - offset = 3.2 - corner = 4 - height = 45.3 - angle = 118 - - tool = Path.Tool() - tool.Name = name - tool.ToolType = typ - tool.Material = mat - tool.Diameter = dia - tool.LengthOffset = offset - tool.FlatRadius = flat - tool.CornerRadius = corner - tool.CuttingEdgeAngle = angle - tool.CuttingEdgeHeight = height - - attrs = tool.templateAttrs() - self.assertEqual(attrs["name"], name) - self.assertEqual(attrs["diameter"], dia) - self.assertEqual(attrs["material"], mat) - self.assertEqual(attrs["tooltype"], typ) - self.assertEqual(attrs["lengthOffset"], offset) - self.assertEqual(attrs["flatRadius"], flat) - self.assertEqual(attrs["cornerRadius"], corner) - self.assertEqual(attrs["cuttingEdgeAngle"], angle) - self.assertEqual(attrs["cuttingEdgeHeight"], height) - return tool - - def test01(self): - """Verify template roundtrip""" - - t0 = self.test00() - t1 = Path.Tool() - t1.setFromTemplate(t0.templateAttrs()) - - self.assertEqual(t0.Name, t1.Name) - self.assertEqual(t0.ToolType, t1.ToolType) - self.assertEqual(t0.Material, t1.Material) - self.assertEqual(t0.Diameter, t1.Diameter) - self.assertEqual(t0.LengthOffset, t1.LengthOffset) - self.assertEqual(t0.FlatRadius, t1.FlatRadius) - self.assertEqual(t0.CornerRadius, t1.CornerRadius) - self.assertEqual(t0.CuttingEdgeAngle, t1.CuttingEdgeAngle) - self.assertEqual(t0.CuttingEdgeHeight, t1.CuttingEdgeHeight) - - def test02(self): - """Verify template dictionary construction""" - - t0 = self.test00() - t1 = Path.Tool(t0.templateAttrs()) - - self.assertEqual(t0.Name, t1.Name) - self.assertEqual(t0.ToolType, t1.ToolType) - self.assertEqual(t0.Material, t1.Material) - self.assertEqual(t0.Diameter, t1.Diameter) - self.assertEqual(t0.LengthOffset, t1.LengthOffset) - self.assertEqual(t0.FlatRadius, t1.FlatRadius) - self.assertEqual(t0.CornerRadius, t1.CornerRadius) - self.assertEqual(t0.CuttingEdgeAngle, t1.CuttingEdgeAngle) - self.assertEqual(t0.CuttingEdgeHeight, t1.CuttingEdgeHeight) diff --git a/src/Mod/Path/PathTests/TestPathToolBit.py b/src/Mod/Path/PathTests/TestPathToolBit.py index 71252c2a11..1b477d3f7e 100644 --- a/src/Mod/Path/PathTests/TestPathToolBit.py +++ b/src/Mod/Path/PathTests/TestPathToolBit.py @@ -20,7 +20,7 @@ # * * # *************************************************************************** -import PathScripts.PathToolBit as PathToolBit +import Path.Tool.Bit as PathToolBit import PathTests.PathTestUtils as PathTestUtils import glob import os diff --git a/src/Mod/Path/PathTests/TestPathToolChangeGenerator.py b/src/Mod/Path/PathTests/TestPathToolChangeGenerator.py index f4ec58b06a..72b0cf80ee 100644 --- a/src/Mod/Path/PathTests/TestPathToolChangeGenerator.py +++ b/src/Mod/Path/PathTests/TestPathToolChangeGenerator.py @@ -21,14 +21,11 @@ # *************************************************************************** import Path -import Generators.toolchange_generator as generator -from Generators.toolchange_generator import SpindleDirection - -import PathScripts.PathLog as PathLog +import Path.Base.Generator.toolchange as generator import PathTests.PathTestUtils as PathTestUtils -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestPathToolChangeGenerator(PathTestUtils.PathTestBase): @@ -39,7 +36,7 @@ class TestPathToolChangeGenerator(PathTestUtils.PathTestBase): "toolnumber": 1, "toollabel": "My Label", "spindlespeed": 500, - "spindledirection": SpindleDirection.OFF, + "spindledirection": generator.SpindleDirection.OFF, } results = generator.generate(**args) @@ -55,7 +52,7 @@ class TestPathToolChangeGenerator(PathTestUtils.PathTestBase): self.assertTrue(toolcommand.Name == "M6") # Turn on the spindle - args["spindledirection"] = SpindleDirection.CW + args["spindledirection"] = generator.SpindleDirection.CW results = generator.generate(**args) self.assertTrue(len(results) == 3) @@ -67,7 +64,7 @@ class TestPathToolChangeGenerator(PathTestUtils.PathTestBase): args["spindlespeed"] = 0 results = generator.generate(**args) self.assertTrue(len(results) == 2) - PathLog.track(results) + Path.Log.track(results) # negative spindlespeed args["spindlespeed"] = -10 diff --git a/src/Mod/Path/PathTests/TestPathToolController.py b/src/Mod/Path/PathTests/TestPathToolController.py index afa2291e10..ab7437f351 100644 --- a/src/Mod/Path/PathTests/TestPathToolController.py +++ b/src/Mod/Path/PathTests/TestPathToolController.py @@ -22,9 +22,8 @@ import FreeCAD import Path -import PathScripts.PathPreferences as PathPreferences -import PathScripts.PathToolBit as PathToolBit -import PathScripts.PathToolController as PathToolController +import Path.Tool.Bit as PathToolBit +import Path.Tool.Controller as PathToolController from PathTests.PathTestUtils import PathTestBase @@ -37,8 +36,6 @@ class TestPathToolController(PathTestBase): FreeCAD.closeDocument(self.doc.Name) def createTool(self, name="t1", diameter=1.75): - if PathPreferences.toolsUseLegacyTools(): - return Path.Tool(name=name, diameter=diameter) attrs = { "shape": None, "name": name, @@ -73,10 +70,7 @@ class TestPathToolController(PathTestBase): self.assertEqual(attrs["hrapid"], "28.0 mm/s") self.assertEqual(attrs["dir"], "Reverse") self.assertEqual(attrs["speed"], 12000) - if PathPreferences.toolsUseLegacyTools(): - self.assertEqual(attrs["tool"], t.templateAttrs()) - else: - self.assertEqual(attrs["tool"], t.Proxy.templateAttrs(t)) + self.assertEqual(attrs["tool"], t.Proxy.templateAttrs(t)) return tc diff --git a/src/Mod/Path/PathTests/TestPathTooltable.py b/src/Mod/Path/PathTests/TestPathTooltable.py deleted file mode 100644 index 9752bc6263..0000000000 --- a/src/Mod/Path/PathTests/TestPathTooltable.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- -# *************************************************************************** -# * Copyright (c) 2017 sliptonic * -# * * -# * 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 Path - -from PathTests.PathTestUtils import PathTestBase - - -class TestPathTooltable(PathTestBase): - def test00(self): - """Verify templateAttrs""" - - t = Path.Tool(name="t", diameter=1.2) - u = Path.Tool(name="u", diameter=3.4) - v = Path.Tool(name="v", diameter=5.6) - - tt = Path.Tooltable() - tt.setTool(3, t) - tt.setTool(1, u) - tt.addTools(v) - - attrs = tt.templateAttrs() - self.assertEqual(3, len(attrs)) - self.assertTrue(1 in attrs) - self.assertFalse(2 in attrs) - self.assertTrue(3 in attrs) - self.assertTrue(4 in attrs) - - self.assertEqual(attrs[1]["name"], "u") - self.assertEqual(attrs[1]["diameter"], 3.4) - self.assertEqual(attrs[3]["name"], "t") - self.assertEqual(attrs[3]["diameter"], 1.2) - self.assertEqual(attrs[4]["name"], "v") - self.assertEqual(attrs[4]["diameter"], 5.6) - return tt - - def test01(self): - """Verify setFromTemplate roundtrip.""" - tt = self.test00() - uu = Path.Tooltable() - uu.setFromTemplate(tt.templateAttrs()) - - self.assertEqual(tt.Content, uu.Content) - - def test02(self): - """Verify template constructor.""" - tt = self.test00() - uu = Path.Tooltable(tt.templateAttrs()) - self.assertEqual(tt.Content, uu.Content) diff --git a/src/Mod/Path/PathTests/TestPathUtil.py b/src/Mod/Path/PathTests/TestPathUtil.py index 04ae92ce58..a22c4f2876 100644 --- a/src/Mod/Path/PathTests/TestPathUtil.py +++ b/src/Mod/Path/PathTests/TestPathUtil.py @@ -21,7 +21,7 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathUtil as PathUtil +import Path.Base.Util as PathUtil import TestSketcherApp from PathTests.PathTestUtils import PathTestBase diff --git a/src/Mod/Path/PathTests/TestPathVcarve.py b/src/Mod/Path/PathTests/TestPathVcarve.py index 51bb80678e..469742b57f 100644 --- a/src/Mod/Path/PathTests/TestPathVcarve.py +++ b/src/Mod/Path/PathTests/TestPathVcarve.py @@ -21,9 +21,8 @@ # *************************************************************************** import FreeCAD -import PathScripts.PathGeom as PathGeom -import PathScripts.PathToolBit as PathToolBit -import PathScripts.PathVcarve as PathVcarve +import Path.Op.Vcarve as PathVcarve +import Path.Tool.Bit as PathToolBit import math from PathTests.PathTestUtils import PathTestBase diff --git a/src/Mod/Path/PathTests/TestPathVoronoi.py b/src/Mod/Path/PathTests/TestPathVoronoi.py index a6a91bf725..169ee5e1c1 100644 --- a/src/Mod/Path/PathTests/TestPathVoronoi.py +++ b/src/Mod/Path/PathTests/TestPathVoronoi.py @@ -23,7 +23,6 @@ import FreeCAD import Part import Path -import PathScripts.PathGeom as PathGeom import PathTests.PathTestUtils as PathTestUtils vd = None @@ -110,7 +109,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e = e0.toShape() self.assertTrue(type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line) self.assertFalse( - PathGeom.pointsCoincide( + Path.Geom.pointsCoincide( e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) ) ) @@ -127,7 +126,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e = e0.toShape(13.7) self.assertTrue(type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line) self.assertFalse( - PathGeom.pointsCoincide( + Path.Geom.pointsCoincide( e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) ) ) @@ -144,7 +143,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e = e0.toShape(2.37, 5.14) self.assertTrue(type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line) self.assertFalse( - PathGeom.pointsCoincide( + Path.Geom.pointsCoincide( e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) ) ) @@ -163,7 +162,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve ) self.assertFalse( - PathGeom.pointsCoincide( + Path.Geom.pointsCoincide( e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) ) ) @@ -182,7 +181,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve ) self.assertFalse( - PathGeom.pointsCoincide( + Path.Geom.pointsCoincide( e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) ) ) @@ -201,7 +200,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve ) self.assertFalse( - PathGeom.pointsCoincide( + Path.Geom.pointsCoincide( e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) ) ) diff --git a/src/Mod/Path/PathTests/TestRefactoredCentroidPost.py b/src/Mod/Path/PathTests/TestRefactoredCentroidPost.py index 4c49c03167..59baeeadf2 100644 --- a/src/Mod/Path/PathTests/TestRefactoredCentroidPost.py +++ b/src/Mod/Path/PathTests/TestRefactoredCentroidPost.py @@ -25,15 +25,13 @@ from importlib import reload import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils -from PathScripts.post import refactored_centroid_post as postprocessor +from Path.Post.scripts import refactored_centroid_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestRefactoredCentroidPost(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestRefactoredGrblPost.py b/src/Mod/Path/PathTests/TestRefactoredGrblPost.py index 9affd355ca..4057a21c45 100644 --- a/src/Mod/Path/PathTests/TestRefactoredGrblPost.py +++ b/src/Mod/Path/PathTests/TestRefactoredGrblPost.py @@ -25,15 +25,13 @@ from importlib import reload import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils -from PathScripts.post import refactored_grbl_post as postprocessor +from Path.Post.scripts import refactored_grbl_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestRefactoredGrblPost(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestRefactoredLinuxCNCPost.py b/src/Mod/Path/PathTests/TestRefactoredLinuxCNCPost.py index 267dc10f84..6da0ee2fc5 100644 --- a/src/Mod/Path/PathTests/TestRefactoredLinuxCNCPost.py +++ b/src/Mod/Path/PathTests/TestRefactoredLinuxCNCPost.py @@ -25,15 +25,13 @@ from importlib import reload import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils -from PathScripts.post import refactored_linuxcnc_post as postprocessor +from Path.Post.scripts import refactored_linuxcnc_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestRefactoredLinuxCNCPost(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestRefactoredMach3Mach4Post.py b/src/Mod/Path/PathTests/TestRefactoredMach3Mach4Post.py index dab611262d..1873ee6a20 100644 --- a/src/Mod/Path/PathTests/TestRefactoredMach3Mach4Post.py +++ b/src/Mod/Path/PathTests/TestRefactoredMach3Mach4Post.py @@ -25,14 +25,12 @@ from importlib import reload import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils -from PathScripts.post import refactored_mach3_mach4_post as postprocessor +from Path.Post.scripts import refactored_mach3_mach4_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestRefactoredMach3Mach4Post(PathTestUtils.PathTestBase): diff --git a/src/Mod/Path/PathTests/TestRefactoredTestPost.py b/src/Mod/Path/PathTests/TestRefactoredTestPost.py index 0d42076929..70614bc28d 100644 --- a/src/Mod/Path/PathTests/TestRefactoredTestPost.py +++ b/src/Mod/Path/PathTests/TestRefactoredTestPost.py @@ -25,15 +25,13 @@ from importlib import reload import FreeCAD -# import Part import Path -import PathScripts.PathLog as PathLog import PathTests.PathTestUtils as PathTestUtils -from PathScripts.post import refactored_test_post as postprocessor +from Path.Post.scripts import refactored_test_post as postprocessor -PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -PathLog.trackModule(PathLog.thisModule()) +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) class TestRefactoredTestPost(PathTestUtils.PathTestBase): @@ -138,7 +136,7 @@ class TestRefactoredTestPost(PathTestUtils.PathTestBase): self.assertEqual(gcode.splitlines()[0], "(Exported by FreeCAD)") self.assertEqual( gcode.splitlines()[1], - "(Post Processor: PathScripts.post.refactored_test_post)", + "(Post Processor: Path.Post.scripts.refactored_test_post)", ) self.assertEqual(gcode.splitlines()[2], "(Cam File: )") self.assertIn("(Output Time: ", gcode.splitlines()[3]) @@ -170,7 +168,7 @@ G21 self.assertEqual(gcode.splitlines()[0], "(Exported by FreeCAD)") self.assertEqual( gcode.splitlines()[1], - "(Post Processor: PathScripts.post.refactored_test_post)", + "(Post Processor: Path.Post.scripts.refactored_test_post)", ) self.assertEqual(gcode.splitlines()[2], "(Cam File: )") self.assertIn("(Output Time: ", gcode.splitlines()[3]) diff --git a/src/Mod/Path/PathTests/boxtest.fcstd b/src/Mod/Path/PathTests/boxtest.fcstd index 2a6e76e292..185ca0bea1 100644 Binary files a/src/Mod/Path/PathTests/boxtest.fcstd and b/src/Mod/Path/PathTests/boxtest.fcstd differ diff --git a/src/Mod/Path/PathTests/boxtest1.fcstd b/src/Mod/Path/PathTests/boxtest1.fcstd index 210307fd72..11c624ef32 100644 Binary files a/src/Mod/Path/PathTests/boxtest1.fcstd and b/src/Mod/Path/PathTests/boxtest1.fcstd differ diff --git a/src/Mod/Path/PathTests/test_filenaming.fcstd b/src/Mod/Path/PathTests/test_filenaming.fcstd index 75bbf08f19..3e418e34d0 100644 Binary files a/src/Mod/Path/PathTests/test_filenaming.fcstd and b/src/Mod/Path/PathTests/test_filenaming.fcstd differ diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 3d0a0606f9..28e76ad1a0 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -36,7 +36,7 @@ from PathTests.TestPathGeom import TestPathGeom from PathTests.TestPathHelpers import TestPathHelpers from PathTests.TestPathHelixGenerator import TestPathHelixGenerator from PathTests.TestPathLog import TestPathLog -from PathTests.TestPathOpTools import TestPathOpTools +from PathTests.TestPathOpUtil import TestPathOpUtil # from PathTests.TestPathPost import TestPathPost from PathTests.TestPathPost import TestPathPostUtils @@ -50,11 +50,9 @@ from PathTests.TestPathSetupSheet import TestPathSetupSheet from PathTests.TestPathStock import TestPathStock from PathTests.TestPathThreadMilling import TestPathThreadMilling from PathTests.TestPathThreadMillingGenerator import TestPathThreadMillingGenerator -from PathTests.TestPathTool import TestPathTool from PathTests.TestPathToolBit import TestPathToolBit from PathTests.TestPathToolChangeGenerator import TestPathToolChangeGenerator from PathTests.TestPathToolController import TestPathToolController -from PathTests.TestPathTooltable import TestPathTooltable from PathTests.TestPathUtil import TestPathUtil from PathTests.TestPathVcarve import TestPathVcarve from PathTests.TestPathVoronoi import TestPathVoronoi @@ -84,7 +82,7 @@ False if TestPathGeom.__name__ else True False if TestPathHelpers.__name__ else True # False if TestPathHelix.__name__ else True False if TestPathLog.__name__ else True -False if TestPathOpTools.__name__ else True +False if TestPathOpUtil.__name__ else True # False if TestPathPost.__name__ else True False if TestPathPostUtils.__name__ else True False if TestPathPreferences.__name__ else True @@ -94,11 +92,9 @@ False if TestPathSetupSheet.__name__ else True False if TestPathStock.__name__ else True False if TestPathThreadMilling.__name__ else True False if TestPathThreadMillingGenerator.__name__ else True -False if TestPathTool.__name__ else True False if TestPathToolBit.__name__ else True False if TestPathToolChangeGenerator.__name__ else True False if TestPathToolController.__name__ else True -False if TestPathTooltable.__name__ else True False if TestPathUtil.__name__ else True False if TestPathVcarve.__name__ else True False if TestPathVoronoi.__name__ else True diff --git a/src/Mod/Path/Tools/toolbit-attributes.py b/src/Mod/Path/Tools/toolbit-attributes.py index 92f91d70fd..326eaa71dd 100755 --- a/src/Mod/Path/Tools/toolbit-attributes.py +++ b/src/Mod/Path/Tools/toolbit-attributes.py @@ -93,8 +93,8 @@ if args.freecad: import FreeCAD import Path -import PathScripts.PathPropertyBag as PathPropertyBag -import PathScripts.PathUtil as PathUtil +import Path.Base.PropertyBag as PathPropertyBag +import Path.Base.Util as PathUtil set_var = None set_val = None