From 2a8ce27ac2336558daa584600cd2a48133f7dbe6 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Wed, 7 Dec 2016 19:22:26 -0600 Subject: [PATCH 01/11] PATH: Add support to visualize probe moves G38.2/3/4/5 --- src/Mod/Path/Gui/DlgSettingsPathColor.cpp | 8 +- src/Mod/Path/Gui/DlgSettingsPathColor.ui | 373 ++++++++++++---------- src/Mod/Path/Gui/ViewProviderPath.cpp | 72 +++-- 3 files changed, 252 insertions(+), 201 deletions(-) diff --git a/src/Mod/Path/Gui/DlgSettingsPathColor.cpp b/src/Mod/Path/Gui/DlgSettingsPathColor.cpp index 7e301ee596..c9b5838588 100644 --- a/src/Mod/Path/Gui/DlgSettingsPathColor.cpp +++ b/src/Mod/Path/Gui/DlgSettingsPathColor.cpp @@ -33,8 +33,8 @@ using namespace PathGui; /* TRANSLATOR PathGui::DlgSettingsPathColor */ /** - * Constructs a DlgSettingsObjectColor which is a child of 'parent', with the - * name 'name' and widget flags set to 'f' + * Constructs a DlgSettingsObjectColor which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' */ DlgSettingsPathColor::DlgSettingsPathColor(QWidget* parent) : PreferencePage(parent) @@ -42,7 +42,7 @@ DlgSettingsPathColor::DlgSettingsPathColor(QWidget* parent) this->setupUi(this); } -/** +/** * Destroys the object and frees any allocated resources */ DlgSettingsPathColor::~DlgSettingsPathColor() @@ -58,6 +58,7 @@ void DlgSettingsPathColor::saveSettings() DefaultPathLineWidth->onSave(); DefaultPathMarkerColor->onSave(); DefaultExtentsColor->onSave(); + DefaultProbePathColor->onSave(); } void DlgSettingsPathColor::loadSettings() @@ -68,6 +69,7 @@ void DlgSettingsPathColor::loadSettings() DefaultPathLineWidth->onRestore(); DefaultPathMarkerColor->onRestore(); DefaultExtentsColor->onRestore(); + DefaultProbePathColor->onRestore(); } /** diff --git a/src/Mod/Path/Gui/DlgSettingsPathColor.ui b/src/Mod/Path/Gui/DlgSettingsPathColor.ui index 226a6d57da..faffa6ff8b 100644 --- a/src/Mod/Path/Gui/DlgSettingsPathColor.ui +++ b/src/Mod/Path/Gui/DlgSettingsPathColor.ui @@ -6,192 +6,225 @@ 0 0 - 359 - 282 + 297 + 281 Path colors - - + + Default Path colors - - - - - - - - 182 - 0 - - - - Default normal path color - - - - - - - The default color for new shapes - - - - 0 - 170 - 0 - - - - DefaultNormalPathColor - - - Mod/Path - - - - - - - - 182 - 0 - - - - Default pathline width - - - - - - - The default line thickness for new shapes - - - px - - - 9 - - - 1 - - - DefaultPathLineWidth - - - Mod/Path - - - - - - - - 182 - 0 - - - - Default path marker color - - - - - - - The default line color for new shapes - - - - 85 - 255 - 0 - - - - DefaultPathMarkerColor - - - Mod/Path - - - - - - - - 182 - 0 - - - - Rapid path color - - - - - - - The default line color for new shapes - - - - 170 - 0 - 0 - - - - DefaultRapidPathColor - - - Mod/Path - - - - - - - Machine extents color - - - - - - - DefaultExtentsColor - - - Mod/Path - - - - - - - - - Qt::Horizontal - - + + + + - 28 - 20 + 182 + 0 - + + Default normal path color + + + + + + + The default color for new shapes + + + + 0 + 170 + 0 + + + + DefaultNormalPathColor + + + Mod/Path + + + + + + + + 182 + 0 + + + + Default pathline width + + + + + + + The default line thickness for new shapes + + + px + + + 9 + + + 1 + + + DefaultPathLineWidth + + + Mod/Path + + + + + + + + 182 + 0 + + + + Default path marker color + + + + + + + The default line color for new shapes + + + + 85 + 255 + 0 + + + + DefaultPathMarkerColor + + + Mod/Path + + + + + + + + 182 + 0 + + + + Rapid path color + + + + + + + The default line color for new shapes + + + + 170 + 0 + 0 + + + + DefaultRapidPathColor + + + Mod/Path + + + + + + + + 182 + 0 + + + + Probe Path color + + + + + + + The default line color for new shapes + + + + 255 + 255 + 5 + + + + DefaultProbePathColor + + + Mod/Path + + + + + + + Machine extents color + + + + + + + DefaultExtentsColor + + + Mod/Path + + + DefaultRapidPathColor_2 + label_8 + label_8 + DefaultProbePathColor - + + + + Qt::Horizontal + + + + 7 + 220 + + + + + Qt::Vertical diff --git a/src/Mod/Path/Gui/ViewProviderPath.cpp b/src/Mod/Path/Gui/ViewProviderPath.cpp index 38348eb476..e2c4322f8c 100644 --- a/src/Mod/Path/Gui/ViewProviderPath.cpp +++ b/src/Mod/Path/Gui/ViewProviderPath.cpp @@ -83,14 +83,14 @@ ViewProviderPath::ViewProviderPath() ADD_PROPERTY_TYPE(LineWidth,(lwidth),"Path",App::Prop_None,"The line width of this path"); ADD_PROPERTY_TYPE(ShowFirstRapid,(true),"Path",App::Prop_None,"Turns the display of the first rapid move on/off"); ADD_PROPERTY_TYPE(ShowNodes,(false),"Path",App::Prop_None,"Turns the display of nodes on/off"); - + pcPathRoot = new Gui::SoFCSelection(); pcPathRoot->style = Gui::SoFCSelection::EMISSIVE; pcPathRoot->highlightMode = Gui::SoFCSelection::AUTO; pcPathRoot->selectionMode = Gui::SoFCSelection::SEL_ON; pcPathRoot->ref(); - + pcTransform = new SoTransform(); pcTransform->ref(); @@ -99,7 +99,7 @@ ViewProviderPath::ViewProviderPath() pcMarkerCoords = new SoCoordinate3(); pcMarkerCoords->ref(); - + pcDrawStyle = new SoDrawStyle(); pcDrawStyle->ref(); pcDrawStyle->style = SoDrawStyle::LINES; @@ -108,17 +108,17 @@ ViewProviderPath::ViewProviderPath() pcLines = new PartGui::SoBrepEdgeSet(); pcLines->ref(); pcLines->coordIndex.setNum(0); - + pcLineColor = new SoMaterial; pcLineColor->ref(); - + pcMatBind = new SoMaterialBinding; pcMatBind->ref(); pcMatBind->value = SoMaterialBinding::OVERALL; pcMarkerColor = new SoBaseColor; pcMarkerColor->ref(); - + NormalColor.touch(); MarkerColor.touch(); } @@ -186,12 +186,16 @@ void ViewProviderPath::onChanged(const App::Property* prop) pcDrawStyle->lineWidth = LineWidth.getValue(); } else if (prop == &NormalColor) { if (colorindex.size() > 0) { - const App::Color& c = NormalColor.getValue(); + const App::Color& c = NormalColor.getValue(); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Path"); unsigned long rcol = hGrp->GetUnsigned("DefaultRapidPathColor",2852126975UL); // dark red (170,0,0) float rr,rg,rb; rr = ((rcol >> 24) & 0xff) / 255.0; rg = ((rcol >> 16) & 0xff) / 255.0; rb = ((rcol >> 8) & 0xff) / 255.0; - + + unsigned long pcol = hGrp->GetUnsigned("DefaultProbePathColor",4293591295UL); // yellow (255,255,5) + float pr,pg,pb; + pr = ((pcol >> 24) & 0xff) / 255.0; pg = ((pcol >> 16) & 0xff) / 255.0; pb = ((pcol >> 8) & 0xff) / 255.0; + pcMatBind->value = SoMaterialBinding::PER_PART; // resizing and writing the color vector: pcLineColor->diffuseColor.setNum(colorindex.size()); @@ -199,8 +203,10 @@ void ViewProviderPath::onChanged(const App::Property* prop) for(unsigned int i=0;idiffuseColor.finishEditing(); } @@ -220,14 +226,14 @@ void ViewProviderPath::updateData(const App::Property* prop) Path::Feature* pcPathObj = static_cast(pcObject); if (prop == &pcPathObj->Path) { - + const Toolpath &tp = pcPathObj->Path.getValue(); if(tp.getSize()==0) { pcLineCoords->point.deleteValues(0); pcMarkerCoords->point.deleteValues(0); return; } - + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Part"); float deviation = hGrp->GetFloat("MeshDeviation",0.2); std::vector points; @@ -237,7 +243,7 @@ void ViewProviderPath::updateData(const App::Property* prop) bool absolute = true; bool absolutecenter = false; bool first = true; - + for (unsigned int i = 0; i < tp.getSize(); i++) { Path::Command cmd = tp.getCommand(i); std::string name = cmd.Name; @@ -250,7 +256,7 @@ void ViewProviderPath::updateData(const App::Property* prop) next.y = last.y; if (!cmd.has("Z")) next.z = last.z; - + if ( (name == "G0") || (name == "G00") || (name == "G1") || (name == "G01") ) { // straight line if ( (!first) || (ShowFirstRapid.getValue() == true) || (name == "G1") || (name == "G01") ) { @@ -273,12 +279,12 @@ void ViewProviderPath::updateData(const App::Property* prop) markers.push_back(last); // startpoint of path } first = false; - + } else if ( (name == "G2") || (name == "G02") || (name == "G3") || (name == "G03") ) { // arc Base::Vector3d norm; Base::Vector3d center; - + if ( (name == "G2") || (name == "G02") ) norm.Set(0,0,-1); else @@ -321,23 +327,23 @@ void ViewProviderPath::updateData(const App::Property* prop) } last = next; colorindex.push_back(1); - + } else if (name == "G90") { // absolute mode absolute = true; - + } else if (name == "G91") { // relative mode absolute = false; - + } else if (name == "G90.1") { // absolute mode absolutecenter = true; - + } else if (name == "G91.1") { // relative mode absolutecenter = false; - + } else if ((name=="G81")||(name=="G82")||(name=="G83")||(name=="G84")||(name=="G85")||(name=="G86")||(name=="G89")){ // drill,tap,bore double r = 0; @@ -373,9 +379,19 @@ void ViewProviderPath::updateData(const App::Property* prop) if (ShowNodes.getValue() == true) markers.push_back(p2); colorindex.push_back(0); - } - } - + + } else if ((name=="G38.2")||(name=="38.3")||(name=="G38.4")||(name=="G38.5")){ + // Straight probe + Base::Vector3d p1(next.x,next.y,last.z); + points.push_back(p1); + colorindex.push_back(0); + points.push_back(next); + colorindex.push_back(2); + Base::Vector3d p3(next.x,next.y,last.z); + points.push_back(p3); + colorindex.push_back(0); + }} + if (!points.empty()) { pcLineCoords->point.deleteValues(0); pcLineCoords->point.setNum(points.size()); @@ -387,20 +403,20 @@ void ViewProviderPath::updateData(const App::Property* prop) int* segs = &ei[0]; pcLines->coordIndex.setNum(points.size()); pcLines->coordIndex.setValues(0,points.size(),(const int32_t*)segs); - + pcMarkerCoords->point.deleteValues(0); - + pcMarkerCoords->point.setNum(markers.size()); for(unsigned int i=0;ipoint.set1Value(i,markers[i].x,markers[i].y,markers[i].z); - + // update the coloring after we changed the color vector NormalColor.touch(); recomputeBoundingBox(); } - + } else if ( prop == &pcPathObj->Placement) { - + Base::Placement pl = *(&pcPathObj->Placement.getValue()); Base::Vector3d pos = pl.getPosition(); double q1, q2, q3, q4; From 2b94b7d919c0ae1c4df0d2e03f05d4904528612d Mon Sep 17 00:00:00 2001 From: sliptonic Date: Thu, 8 Dec 2016 10:26:58 -0600 Subject: [PATCH 02/11] PATH: Simple command to build a probe grid. --- .../Gui/Resources/panels/ProbeGridEdit.ui | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 src/Mod/Path/Gui/Resources/panels/ProbeGridEdit.ui diff --git a/src/Mod/Path/Gui/Resources/panels/ProbeGridEdit.ui b/src/Mod/Path/Gui/Resources/panels/ProbeGridEdit.ui new file mode 100644 index 0000000000..7882265cb2 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/panels/ProbeGridEdit.ui @@ -0,0 +1,210 @@ + + + Dialog + + + + 0 + 0 + 273 + 287 + + + + + 0 + 0 + + + + Dialog + + + + + 30 + 240 + 231 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 0 + 0 + 261 + 231 + + + + + + + + + + Probe Area Shape + + + + + + + + BoundBox + + + + + Perimeter + + + + + + + + + + + + + + Probe Distance + + + + + + + 0.100000000000000 + + + 5.000000000000000 + + + + + + + + + + + + + Probe Feed Rate + + + + + + + 50.000000000000000 + + + + + + + + + + Probe Points: + + + + + + + + + + X: + + + + + + + 5 + + + + + + + Qt::Horizontal + + + + 77 + 20 + + + + + + + + Y: + + + + + + + 5 + + + + + + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From 7421a3e9ee03a9e8ebf9c240f0a29477151c469d Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sun, 11 Dec 2016 12:43:10 -0600 Subject: [PATCH 03/11] PATH: Highlighting in Inspect --- src/Mod/Path/Gui/DlgSettingsPathColor.cpp | 2 + src/Mod/Path/Gui/DlgSettingsPathColor.ui | 77 ++++++++++++++++++----- src/Mod/Path/PathScripts/PathInspect.py | 65 +++++++++++++++++-- 3 files changed, 123 insertions(+), 21 deletions(-) diff --git a/src/Mod/Path/Gui/DlgSettingsPathColor.cpp b/src/Mod/Path/Gui/DlgSettingsPathColor.cpp index c9b5838588..f644bf056c 100644 --- a/src/Mod/Path/Gui/DlgSettingsPathColor.cpp +++ b/src/Mod/Path/Gui/DlgSettingsPathColor.cpp @@ -59,6 +59,7 @@ void DlgSettingsPathColor::saveSettings() DefaultPathMarkerColor->onSave(); DefaultExtentsColor->onSave(); DefaultProbePathColor->onSave(); + DefaultHighlightPathColor->onSave(); } void DlgSettingsPathColor::loadSettings() @@ -70,6 +71,7 @@ void DlgSettingsPathColor::loadSettings() DefaultPathMarkerColor->onRestore(); DefaultExtentsColor->onRestore(); DefaultProbePathColor->onRestore(); + DefaultHighlightPathColor->onRestore(); } /** diff --git a/src/Mod/Path/Gui/DlgSettingsPathColor.ui b/src/Mod/Path/Gui/DlgSettingsPathColor.ui index faffa6ff8b..fa7df4cd09 100644 --- a/src/Mod/Path/Gui/DlgSettingsPathColor.ui +++ b/src/Mod/Path/Gui/DlgSettingsPathColor.ui @@ -6,8 +6,8 @@ 0 0 - 297 - 281 + 310 + 304 @@ -204,13 +204,69 @@ + + + + + 182 + 0 + + + + Path Highlight Color + + + + + + + The default line color for new shapes + + + + 255 + 125 + 0 + + + + DefaultHighlightPathColor + + + Mod/Path + + + - DefaultRapidPathColor_2 - label_8 + label_6 + DefaultNormalPathColor + label_9 + DefaultPathLineWidth + label_10 + DefaultPathMarkerColor + label_7 + DefaultRapidPathColor + label + DefaultExtentsColor label_8 DefaultProbePathColor + label_11 + DefaultHighlightPathColor + + + + Qt::Vertical + + + + 20 + 217 + + + + @@ -224,19 +280,6 @@ - - - - Qt::Vertical - - - - 20 - 217 - - - - diff --git a/src/Mod/Path/PathScripts/PathInspect.py b/src/Mod/Path/PathScripts/PathInspect.py index 4312a12088..5119620602 100644 --- a/src/Mod/Path/PathScripts/PathInspect.py +++ b/src/Mod/Path/PathScripts/PathInspect.py @@ -25,7 +25,7 @@ from PySide import QtCore, QtGui import FreeCAD import FreeCADGui - +import Path # Qt tanslation handling try: _encoding = QtGui.QApplication.UnicodeUTF8 @@ -110,11 +110,21 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter): class GCodeEditorDialog(QtGui.QDialog): - def __init__(self, parent=FreeCADGui.getMainWindow()): - + def __init__(self, PathObj, parent=FreeCADGui.getMainWindow()): + self.PathObj = PathObj QtGui.QDialog.__init__(self, parent) layout = QtGui.QVBoxLayout(self) + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") + c = p.GetUnsigned("DefaultHighlightPathColor", 4286382335 ) + Q = QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF)) + highlightcolor = (Q.red()/255., Q.green()/255., Q.blue()/255., Q.alpha()/255.) + + self.selectionobj = FreeCAD.ActiveDocument.addObject("Path::Feature","selection") + self.selectionobj.ViewObject.LineWidth = 4 + self.selectionobj.ViewObject.NormalColor = highlightcolor + self.selectionobj.ViewObject.ShowFirstRapid = False + # nice text editor widget for editing the gcode self.editor = QtGui.QTextEdit() font = QtGui.QFont() @@ -140,6 +150,53 @@ class GCodeEditorDialog(QtGui.QDialog): layout.addWidget(self.buttons) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) + self.editor.selectionChanged.connect(self.hightlightpath) + self.finished.connect(self.cleanup) + + def cleanup(self): + FreeCAD.ActiveDocument.removeObject(self.selectionobj.Name) + + def hightlightpath(self): + cursor = self.editor.textCursor() + sp = cursor.selectionStart() + ep = cursor.selectionEnd() + cursor.setPosition(sp) + startrow = cursor.blockNumber() + cursor.setPosition(ep) + endrow = cursor.blockNumber() + + commands = self.PathObj.Commands + + #Derive the starting position for the first selected command + prevX = prevY = prevZ = None + prevcommands = commands[:startrow] + prevcommands.reverse() + for c in prevcommands: + if prevX is None: + if c.Parameters.get("X") is not None: + prevX = c.Parameters.get("X") + if prevY is None: + if c.Parameters.get("Y") is not None: + prevY = c.Parameters.get("Y") + if prevZ is None: + if c.Parameters.get("Z") is not None: + prevZ = c.Parameters.get("Z") + if prevX is not None and prevY is not None and prevZ is not None: + break + if prevX is None: + prevX = 0.0 + if prevY is None: + prevY = 0.0 + if prevZ is None: + prevZ = 0.0 + + #Build a new path with selection + p = Path.Path() + firstrapid = Path.Command("G0", {"X": prevX, "Y":prevY, "Z":prevZ}) + + selectionpath = [firstrapid] + commands[startrow:endrow +1] + p.Commands = selectionpath + self.selectionobj.Path = p def show(obj): @@ -147,7 +204,7 @@ def show(obj): if hasattr(obj, "Path"): if obj.Path: - dia = GCodeEditorDialog() + dia = GCodeEditorDialog(obj.Path) dia.editor.setText(obj.Path.toGCode()) result = dia.exec_() # exec_() returns 0 or 1 depending on the button pressed (Ok or From 66210c7888139f75e386013c50d0c43259ad2ad2 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Thu, 17 Nov 2016 10:16:41 -0600 Subject: [PATCH 04/11] PATH: Delete misplaced and unused files --- src/Mod/Path/InitGui.py | 1 - src/Mod/Path/PathScripts/DlgToolLibrary.ui | 145 ---- .../Path/PathScripts/DlgToolTableEditor.ui | 244 ------- src/Mod/Path/PathScripts/PathInspect.py | 26 +- src/Mod/Path/PathScripts/PathJob.py | 2 - src/Mod/Path/PathScripts/PathKurveUtils.py | 15 +- src/Mod/Path/PathScripts/PathMillFace.py | 2 +- src/Mod/Path/PathScripts/PathRemote.py | 478 -------------- src/Mod/Path/PathScripts/PathSelection.py | 68 +- src/Mod/Path/PathScripts/PathStrategy.py | 401 ------------ .../PathScripts/PathToolLibraryManager.py | 24 +- src/Mod/Path/PathScripts/PathUtils.py | 617 +++++++++--------- src/Mod/Path/PathScripts/PostUtils.py | 28 +- src/Mod/Path/PathScripts/ToolAdd.ui | 190 ------ src/Mod/Path/PathScripts/nc/drag_knife.py | 72 -- src/Mod/Path/PathScripts/nc/makerbotHBP.py | 306 --------- src/Mod/Path/PathScripts/nc/makerbot_codes.py | 128 ---- src/Mod/Path/PathScripts/nc/printbot3d.py | 53 -- .../Path/PathScripts/nc/printbot3d_read.py | 17 - .../Path/PathScripts/toollibrarymanager.py | 242 ------- 20 files changed, 385 insertions(+), 2674 deletions(-) delete mode 100644 src/Mod/Path/PathScripts/DlgToolLibrary.ui delete mode 100644 src/Mod/Path/PathScripts/DlgToolTableEditor.ui delete mode 100644 src/Mod/Path/PathScripts/PathRemote.py delete mode 100644 src/Mod/Path/PathScripts/PathStrategy.py delete mode 100644 src/Mod/Path/PathScripts/ToolAdd.ui delete mode 100644 src/Mod/Path/PathScripts/nc/drag_knife.py delete mode 100644 src/Mod/Path/PathScripts/nc/makerbotHBP.py delete mode 100644 src/Mod/Path/PathScripts/nc/makerbot_codes.py delete mode 100644 src/Mod/Path/PathScripts/nc/printbot3d.py delete mode 100644 src/Mod/Path/PathScripts/nc/printbot3d_read.py delete mode 100644 src/Mod/Path/PathScripts/toollibrarymanager.py diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py index 7c34fd592e..bee382340e 100644 --- a/src/Mod/Path/InitGui.py +++ b/src/Mod/Path/InitGui.py @@ -67,7 +67,6 @@ class PathWorkbench (Workbench): from PathScripts import PathSimpleCopy from PathScripts import PathEngrave from PathScripts import PathSurface - from PathScripts import PathRemote from PathScripts import PathSanity from PathScripts import DragknifeDressup from PathScripts import PathContour diff --git a/src/Mod/Path/PathScripts/DlgToolLibrary.ui b/src/Mod/Path/PathScripts/DlgToolLibrary.ui deleted file mode 100644 index e26daff490..0000000000 --- a/src/Mod/Path/PathScripts/DlgToolLibrary.ui +++ /dev/null @@ -1,145 +0,0 @@ - - - Dialog - - - - 0 - 0 - 946 - 614 - - - - Dialog - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Add Selected Tools to Project - - - - - - - Tool Library - - - - - - Delete - - - - - - - Import... - - - - - - - Move up - - - - - - - Add new List - - - - - - - Move down - - - - - - - New Tool - - - - - - - - 0 - 0 - - - - true - - - - - - - Export... - - - - - - - - - - - - - - - buttonBox - accepted() - Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/Mod/Path/PathScripts/DlgToolTableEditor.ui b/src/Mod/Path/PathScripts/DlgToolTableEditor.ui deleted file mode 100644 index 9bae38f3f5..0000000000 --- a/src/Mod/Path/PathScripts/DlgToolTableEditor.ui +++ /dev/null @@ -1,244 +0,0 @@ - - - Dialog - - - - 0 - 0 - 807 - 555 - - - - Dialog - - - - - - Tool Properties - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Name - - - - - - - - - - Type - - - - - - - - - - Material - - - - - - - - - - Diameter - - - - - - - mm - - - - - - - Length Offset - - - - - - - mm - - - - - - - Flat Radius - - - - - - - mm - - - - - - - Corner Radius - - - - - - - mm - - - - - - - Cutting Edge Angle - - - - - - - ° - - - - - - - Cutting Edge Height - - - - - - - mm - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Tool List - - - - - - Delete - - - - - - - Move up - - - - - - - Import... - - - - - - - Export... - - - - - - - Add new - - - - - - - - - - Move down - - - - - - - - - - - - buttonBox - accepted() - Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/Mod/Path/PathScripts/PathInspect.py b/src/Mod/Path/PathScripts/PathInspect.py index 4312a12088..6c2125b3a6 100644 --- a/src/Mod/Path/PathScripts/PathInspect.py +++ b/src/Mod/Path/PathScripts/PathInspect.py @@ -37,21 +37,21 @@ except AttributeError: return QtGui.QApplication.translate(context, text, disambig) -class OldHighlighter(QtGui.QSyntaxHighlighter): +# class OldHighlighter(QtGui.QSyntaxHighlighter): - def highlightBlock(self, text): +# def highlightBlock(self, text): - myClassFormat = QtGui.QTextCharFormat() - myClassFormat.setFontWeight(QtGui.QFont.Bold) - myClassFormat.setForeground(QtCore.Qt.green) - # the regex pattern to be colored - pattern = "(G.*?|M.*?)\\s" - expression = QtCore.QRegExp(pattern) - index = text.index(expression) - while index >= 0: - length = expression.matchedLength() - setFormat(index, length, myClassFormat) - index = text.index(expression, index + length) +# myClassFormat = QtGui.QTextCharFormat() +# myClassFormat.setFontWeight(QtGui.QFont.Bold) +# myClassFormat.setForeground(QtCore.Qt.green) +# # the regex pattern to be colored +# pattern = "(G.*?|M.*?)\\s" +# expression = QtCore.QRegExp(pattern) +# index = text.index(expression) +# while index >= 0: +# length = expression.matchedLength() +# setFormat(index, length, myClassFormat) +# index = text.index(expression, index + length) class GCodeHighlighter(QtGui.QSyntaxHighlighter): diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index 5f788e82a2..27ee74515d 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -28,8 +28,6 @@ from PySide import QtCore, QtGui from PathScripts.PathPostProcessor import PostProcessor from PathScripts.PathPreferences import PathPreferences import Draft -import os -import glob FreeCADGui = None diff --git a/src/Mod/Path/PathScripts/PathKurveUtils.py b/src/Mod/Path/PathScripts/PathKurveUtils.py index ccdca4489f..c10927840d 100644 --- a/src/Mod/Path/PathScripts/PathKurveUtils.py +++ b/src/Mod/Path/PathScripts/PathKurveUtils.py @@ -22,16 +22,9 @@ # * * # *************************************************************************** '''PathKurveUtils - functions needed for using libarea (created by Dan Heeks) for making simple CNC profile paths ''' -import FreeCAD -from FreeCAD import Vector -import FreeCADGui as Gui import Part -import DraftGeomUtils -import DraftVecUtils -from DraftGeomUtils import geomType import math import area -import Path from PathScripts import PathUtils from nc.nc import * import PathScripts.nc.iso @@ -209,7 +202,7 @@ def profile(curve, side_of_line, radius=1.0, vertfeed=0.0, horizfeed=0.0, offset layer_count = int((start_depth - final_depth) / stepdown) if layer_count * stepdown + 0.00001 < start_depth - final_depth: layer_count += 1 - current_start_depth = start_depth + # current_start_depth = start_depth prev_depth = start_depth for i in range(1, layer_count + 1): if i == layer_count: @@ -388,7 +381,7 @@ def profile2(curve, direction="on", radius=1.0, vertfeed=0.0, # do multiple depths depths = depthparams.get_depths() - current_start_depth = depthparams.start_depth + # current_start_depth = depthparams.start_depth # tags if len(tags) > 0: @@ -532,7 +525,7 @@ class Tag: height_above_depth = tag_top_depth - depth ramp_width_at_depth = height_above_depth / math.tan(self.angle) - cut_depth = start_depth - depth + # cut_depth = start_depth - depth half_flat_top = radius + self.width / 2 d = curve.PointToPerim(self.p) @@ -574,7 +567,7 @@ class Tag: def get_z_at_perim(self, current_perim, curve, radius, start_depth, depth, final_depth): # return the z for this position on the kurve ( specified by current_perim ), for this tag # if the position is not within the tag, then depth is returned - cut_depth = start_depth - depth + # cut_depth = start_depth - depth half_flat_top = radius + self.width / 2 z = depth diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/PathScripts/PathMillFace.py index 4ec82e289f..80f11320e3 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/PathScripts/PathMillFace.py @@ -224,7 +224,7 @@ class ObjectFace: self.vertFeed = 100 self.horizFeed = 100 self.vertRapid = 100 - self.horiRrapid = 100 + self.horizRrapid = 100 self.radius = 0.25 obj.ToolNumber = 0 obj.ToolDescription = "UNDEFINED" diff --git a/src/Mod/Path/PathScripts/PathRemote.py b/src/Mod/Path/PathScripts/PathRemote.py deleted file mode 100644 index 8e0d78c3e4..0000000000 --- a/src/Mod/Path/PathScripts/PathRemote.py +++ /dev/null @@ -1,478 +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 * -# * * -# *************************************************************************** - -import FreeCAD -import Path -from PathScripts import PathUtils -import urllib2 -import json - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - -__title__ = "Path Remote Operation" -__author__ = "sliptonic (Brad Collette)" -__url__ = "http://www.freecadweb.org" - -"""Path Remote processing object and FreeCAD command""" - -# Qt tanslation handling -try: - _encoding = QtGui.QApplication.UnicodeUTF8 - - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig, _encoding) -except AttributeError: - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig) - - -class ObjectRemote: - - def __init__(self, obj): - - obj.addProperty("App::PropertyLinkSubList", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","The base geometry of this toolpath")) - obj.addProperty("App::PropertyBool", "Active", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","Make False, to prevent operation from generating code")) - obj.addProperty("App::PropertyString", "Comment", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional comment for this profile")) - obj.addProperty("App::PropertyString", "UserLabel", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","User Assigned Label")) - - obj.addProperty("App::PropertyString", "URL", "API", QtCore.QT_TRANSLATE_NOOP("App::Property","The Base URL of the remote path service")) - obj.addProperty("App::PropertyStringList", "proplist", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","list of remote properties")) - obj.setEditorMode('proplist', 2) # make this hidden - - # Tool Properties - obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool",QtCore.QT_TRANSLATE_NOOP("App::Property","The tool number in use")) - obj.ToolNumber = (0, 0, 1000, 0) - obj.setEditorMode('ToolNumber', 1) # make this read only - obj.addProperty("App::PropertyString", "ToolDescription", "Tool", QtCore.QT_TRANSLATE_NOOP("App::Property","The description of the tool ")) - obj.setEditorMode('ToolDescription', 1) # make this read onlyt - - # Depth Properties - obj.addProperty("App::PropertyFloat", "ClearanceHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","The height needed to clear clamps and obstructions")) - obj.addProperty("App::PropertyFloat", "SafeHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Rapid Safety Height between locations.")) - obj.addProperty("App::PropertyFloatConstraint", "StepDown", "Step", QtCore.QT_TRANSLATE_NOOP("App::Property","Incremental Step Down of Tool")) - obj.StepDown = (0.0, 0.01, 100.0, 0.5) - obj.addProperty("App::PropertyFloat", "StartDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Starting Depth of Tool- first cut depth in Z")) - obj.addProperty("App::PropertyFloat", "FinalDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Final Depth of Tool- lowest value in Z")) - obj.addProperty("App::PropertyFloat", "FinishDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Maximum material removed on final pass.")) - - obj.Proxy = self - - def addbaseobject(self, obj, ss, sub=""): - baselist = obj.Base - if len(baselist) == 0: # When adding the first base object, guess at heights - try: - bb = ss.Shape.BoundBox # parent boundbox - subobj = ss.Shape.getElement(sub) - fbb = subobj.BoundBox # feature boundbox - obj.StartDepth = bb.ZMax - obj.ClearanceHeight = bb.ZMax + 5.0 - obj.SafeHeight = bb.ZMax + 3.0 - - if fbb.ZMax < bb.ZMax: - obj.FinalDepth = fbb.ZMax - else: - obj.FinalDepth = bb.ZMin - except: - obj.StartDepth = 5.0 - obj.ClearanceHeight = 10.0 - obj.SafeHeight = 8.0 - - item = (ss, sub) - if item in baselist: - FreeCAD.Console.PrintWarning("this object already in the list" + "\n") - else: - baselist.append(item) - obj.Base = baselist - self.execute(obj) - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - def onChanged(self, obj, prop): - - "'''Do something when a property has changed'''" - if prop == "URL": - url = obj.URL + "/api/v1.0/properties" - try: - response = urllib2.urlopen(url) - except: - print "service not defined or not responding" - print "len: " + str(len(obj.proplist)) - if len(obj.proplist) != 0: - for prop in obj.proplist: - print "removing: " + str(prop) - obj.removeProperty(prop) - pl = obj.proplist - pl = [] - obj.proplist = pl - return - - data = json.load(response) - - properties = data['properties'] - for prop in obj.proplist: - print "removing: " + str(prop) - obj.removeProperty(prop) - - pl = obj.proplist - pl = [] - for prop in properties: - obj.addProperty( - prop['type'], - prop['propertyname'], - "Remote", - prop['description']) - pl.append(prop['propertyname']) - print "adding: " + str(prop) - obj.proplist = pl - - if prop == "UserLabel": - obj.Label = obj.UserLabel + " :" + obj.ToolDescription - - def execute(self, obj): - output = "" - if obj.Comment != "": - output += '(' + str(obj.Comment)+')\n' - - toolLoad = PathUtils.getLastToolLoad(obj) - if toolLoad is None or toolLoad.ToolNumber == 0: - self.vertFeed = 100 - self.horizFeed = 100 - self.radius = 0.25 - obj.ToolNumber = 0 - obj.ToolDescription = "UNDEFINED" - else: - self.vertFeed = toolLoad.VertFeed.Value - self.horizFeed = toolLoad.HorizFeed.Value - tool = PathUtils.getTool(obj, toolLoad.ToolNumber) - self.radius = tool.Diameter/2 - obj.ToolNumber = toolLoad.ToolNumber - obj.ToolDescription = toolLoad.Name - - if obj.UserLabel == "": - obj.Label = obj.Name + " :" + obj.ToolDescription - else: - obj.Label = obj.UserLabel + " :" + obj.ToolDescription - - output += "(remote gcode goes here)" - - if obj.Active: - path = Path.Path(output) - obj.Path = path - obj.ViewObject.Visibility = True - - else: - path = Path.Path("(inactive operation)") - obj.Path = path - obj.ViewObject.Visibility = False - - -class ViewProviderRemote: - def __init__(self, obj): - obj.Proxy = self - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - def getIcon(self): - return ":/icons/Path-Remote.svg" - - def onChanged(self, obj, prop): - # this is executed when a property of the VIEW PROVIDER changes - pass - - def updateData(self, obj, prop): # optional - # this is executed when a property of the APP OBJECT changes - pass - - def setEdit(self, vobj, mode=0): - FreeCADGui.Control.closeDialog() - taskd = TaskPanel() - taskd.obj = vobj.Object - FreeCADGui.Control.showDialog(taskd) - taskd.setupUi() - return True - - def unsetEdit(self, vobj, mode): - # this is executed when the user cancels or terminates edit mode - pass - - -class _RefreshRemotePath: - def GetResources(self): - return {'Pixmap': 'Path-Refresh', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Refresh Remote Path Data"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Refresh Remote Path Data")} - - def IsActive(self): - return FreeCAD.ActiveDocument is not None - - def refresh(self): - obj = FreeCADGui.Selection.getSelection()[0] - values = {} - - for i in obj.PropertiesList: - if obj.getGroupOfProperty(i) in ["Remote"]: - values.update({i: obj.getPropertyByName(i)}) - - if obj.getGroupOfProperty(i) in ["Depth"]: - print str(i) - values.update({i: obj.getPropertyByName(i)}) - - if obj.getGroupOfProperty(i) in ["Step"]: - values.update({i: obj.getPropertyByName(i)}) - - if obj.getGroupOfProperty(i) in ["Tool"]: - tool = PathUtils.getTool(obj, obj.ToolNumber) - if tool: - tradius = tool.Diameter/2 - tlength = tool.LengthOffset - ttype = tool.ToolType - else: - tradius = 0.25 - tlength = 1 - ttype = "undefined" - - values.update({"tool_diameter": tradius}) - values.update({"tool_length": tlength}) - values.update({"tool_type": ttype}) - - payload = json.dumps(values) - - url = obj.URL + "/api/v1.0/path" - print url - try: - req = urllib2.Request(url) - req.add_header('Content-Type', 'application/json') - response = urllib2.urlopen(req, payload) - data = json.load(response) - except: - print "service not defined or not responding" - return - - path = data['path'] - output = "" - for command in path: - output += command['command'] - path = Path.Path(output) - obj.Path = path - - def Activated(self): - self.refresh() - - -class CommandPathRemote: - - def GetResources(self): - return {'Pixmap': 'Path-Remote', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Remote"), - 'Accel': "P, R", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Request a Path from a remote cloud service")} - - 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): - ztop = 10.0 - zbottom = 0.0 - - FreeCAD.ActiveDocument.openTransaction(translate("Path_Remote", "Create remote path operation")) - FreeCADGui.addModule("PathScripts.PathRemote") - FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "Remote")') - FreeCADGui.doCommand('PathScripts.PathRemote.ObjectRemote(obj)') - FreeCADGui.doCommand('obj.Active = True') - FreeCADGui.doCommand('PathScripts.PathRemote.ViewProviderRemote(obj.ViewObject)') - FreeCADGui.doCommand('from PathScripts import PathUtils') - FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 2)) - FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop)) - FreeCADGui.doCommand('obj.SafeHeight = ' + str(ztop + 2)) - FreeCADGui.doCommand('obj.StepDown = ' + str((ztop-zbottom)/8)) - - FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom)) - FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)') - - FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() - FreeCADGui.doCommand('obj.ViewObject.startEditing()') - - -class TaskPanel: - def __init__(self): - self.form = FreeCADGui.PySideUic.loadUi(":/panels/RemoteEdit.ui") - - def accept(self): - self.getFields() - - FreeCADGui.ActiveDocument.resetEdit() - FreeCADGui.Control.closeDialog() - FreeCAD.ActiveDocument.recompute() - FreeCADGui.Selection.removeObserver(self.s) - - def reject(self): - FreeCADGui.Control.closeDialog() - FreeCAD.ActiveDocument.recompute() - FreeCADGui.Selection.removeObserver(self.s) - - def getRemoteFields(self): - self.getFields() - self.obj.URL = self.form.remoteURL.text() - print "getRemote:320" - - def getFields(self): - if self.obj: - if hasattr(self.obj, "StartDepth"): - self.obj.StartDepth = float(self.form.startDepth.text()) - if hasattr(self.obj, "FinalDepth"): - self.obj.FinalDepth = float(self.form.finalDepth.text()) - if hasattr(self.obj, "SafeHeight"): - self.obj.SafeHeight = float(self.form.safeHeight.text()) - if hasattr(self.obj, "ClearanceHeight"): - self.obj.ClearanceHeight = float(self.form.clearanceHeight.text()) - if hasattr(self.obj, "StepDown"): - self.obj.StepDown = float(self.form.stepDown.value()) - - self.obj.Proxy.execute(self.obj) - - def open(self): - self.s = SelObserver() - FreeCADGui.Selection.addObserver(self.s) - - def addBase(self): - # check that the selection contains exactly what we want - selection = FreeCADGui.Selection.getSelectionEx() - - if not len(selection) >= 1: - FreeCAD.Console.PrintError(translate("PathProject", "Please select at least one suitable object\n")) - return - for s in selection: - if s.HasSubObjects: - for i in s.SubElementNames: - self.obj.Proxy.addbaseobject(self.obj, s.Object, i) - else: - self.obj.Proxy.addbaseobject(self.obj, s.Object) - - self.setupUi() # defaults may have changed. Reload. - self.form.baseList.clear() - for i in self.obj.Base: - self.form.baseList.addItem(i[0].Name + "." + i[1]) - - def deleteBase(self): - dlist = self.form.baseList.selectedItems() - for d in dlist: - newlist = [] - for i in self.obj.Base: - if not i[0].Name == d.text(): - newlist.append(i) - self.obj.Base = newlist - self.form.baseList.takeItem(self.form.baseList.row(d)) - self.obj.Proxy.execute(self.obj) - FreeCAD.ActiveDocument.recompute() - - def itemActivated(self): - FreeCADGui.Selection.clearSelection() - slist = self.form.baseList.selectedItems() - for i in slist: - o = FreeCAD.ActiveDocument.getObject(i.text()) - FreeCADGui.Selection.addSelection(o) - FreeCADGui.updateGui() - - def reorderBase(self): - newlist = [] - for i in range(self.form.baseList.count()): - s = self.form.baseList.item(i).text() - obj = FreeCAD.ActiveDocument.getObject(s) - newlist.append(obj) - self.obj.Base = newlist - self.obj.Proxy.execute(self.obj) - FreeCAD.ActiveDocument.recompute() - - def getStandardButtons(self): - return int(QtGui.QDialogButtonBox.Ok) - - def changeURL(self): - from urlparse import urlparse - t = self.form.remoteURL.text() - if t == '' and self.obj.URL != '': # if the url was deleted, cleanup. - self.obj.URL = '' - - if urlparse(t).scheme != '' and t != self.obj.URL: # validate new url. - self.obj.URL = t - # next make sure the property fields reflect the current attached service - for p in self.obj.proplist: - print p - - def setupUi(self): - self.form.startDepth.setText(str(self.obj.StartDepth)) - self.form.finalDepth.setText(str(self.obj.FinalDepth)) - self.form.safeHeight.setText(str(self.obj.SafeHeight)) - self.form.clearanceHeight.setText(str(self.obj.ClearanceHeight)) - self.form.remoteURL.setText(str(self.obj.URL)) - - for i in self.obj.Base: - self.form.baseList.addItem(i[0].Name) - - # Connect Signals and Slots - self.form.startDepth.editingFinished.connect(self.getFields) - self.form.finalDepth.editingFinished.connect(self.getFields) - self.form.safeHeight.editingFinished.connect(self.getFields) - self.form.clearanceHeight.editingFinished.connect(self.getFields) - - self.form.addBase.clicked.connect(self.addBase) - self.form.baseList.itemSelectionChanged.connect(self.itemActivated) - self.form.deleteBase.clicked.connect(self.deleteBase) - self.form.reorderBase.clicked.connect(self.reorderBase) - - self.form.remoteURL.editingFinished.connect(self.changeURL) - - -class SelObserver: - def __init__(self): - import PathScripts.PathSelection as PST - - def __del__(self): - import PathScripts.PathSelection as PST - PST.clear() - - def addSelection(self, doc, obj, sub, pnt): - FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')') - FreeCADGui.updateGui() - -if FreeCAD.GuiUp: - # register the FreeCAD command - FreeCADGui.addCommand('Path_Remote', CommandPathRemote()) - FreeCADGui.addCommand('Refresh_Path', _RefreshRemotePath()) - -FreeCAD.Console.PrintLog("Loading PathRemote... done\n") diff --git a/src/Mod/Path/PathScripts/PathSelection.py b/src/Mod/Path/PathScripts/PathSelection.py index a6566e9258..3fa24b653e 100644 --- a/src/Mod/Path/PathScripts/PathSelection.py +++ b/src/Mod/Path/PathScripts/PathSelection.py @@ -25,44 +25,44 @@ import FreeCAD import FreeCADGui -from FreeCAD import Vector +#from FreeCAD import Vector -def equals(p1, p2): - '''returns True if vertexes have same coordinates within precision amount of digits ''' - precision = 12 - p = precision - u = Vector(p1.X, p1.Y, p1.Z) - v = Vector(p2.X, p2.Y, p2.Z) - vector = (u.sub(v)) - isNull = (round(vector.x, p) == 0 and round(vector.y, p) == 0 and round(vector.z, p) == 0) - return isNull +# def equals(p1, p2): +# '''returns True if vertexes have same coordinates within precision amount of digits ''' +# precision = 12 +# p = precision +# u = Vector(p1.X, p1.Y, p1.Z) +# v = Vector(p2.X, p2.Y, p2.Z) +# vector = (u.sub(v)) +# isNull = (round(vector.x, p) == 0 and round(vector.y, p) == 0 and round(vector.z, p) == 0) +# return isNull -def segments(poly): - ''' A sequence of (x,y) numeric coordinates pairs ''' - return zip(poly, poly[1:] + [poly[0]]) +# def segments(poly): +# ''' A sequence of (x,y) numeric coordinates pairs ''' +# return zip(poly, poly[1:] + [poly[0]]) -def check_clockwise(poly): - ''' - check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise - based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)] - ''' - clockwise = False - if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0: - clockwise = not clockwise - return clockwise +# def check_clockwise(poly): +# ''' +# check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise +# based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)] +# ''' +# clockwise = False +# if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0: +# clockwise = not clockwise +# return clockwise -class FGate: - def allow(self, doc, obj, sub): - return (sub[0:4] == 'Face') +# class FGate: +# def allow(self, doc, obj, sub): +# return (sub[0:4] == 'Face') -class VGate: - def allow(self, doc, obj, sub): - return (sub[0:6] == 'Vertex') +# class VGate: +# def allow(self, doc, obj, sub): +# return (sub[0:6] == 'Vertex') class EGate: @@ -182,14 +182,14 @@ def contourselect(): FreeCADGui.Selection.addSelectionGate(CONTOURGate()) FreeCAD.Console.PrintWarning("Contour Select Mode\n") -def fselect(): - FreeCADGui.Selection.addSelectionGate(FGate()) - FreeCAD.Console.PrintWarning("Face Select Mode\n") +# def fselect(): +# FreeCADGui.Selection.addSelectionGate(FGate()) +# FreeCAD.Console.PrintWarning("Face Select Mode\n") -def vselect(): - FreeCADGui.Selection.addSelectionGate(VGate()) - FreeCAD.Console.PrintWarning("Vertex Select Mode\n") +# def vselect(): +# FreeCADGui.Selection.addSelectionGate(VGate()) +# FreeCAD.Console.PrintWarning("Vertex Select Mode\n") def eselect(): diff --git a/src/Mod/Path/PathScripts/PathStrategy.py b/src/Mod/Path/PathScripts/PathStrategy.py deleted file mode 100644 index baeb89a8cb..0000000000 --- a/src/Mod/Path/PathScripts/PathStrategy.py +++ /dev/null @@ -1,401 +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 * -# * * -# *************************************************************************** - -import FreeCAD -import Path -from PathScripts import PathUtils - -if FreeCAD.GuiUp: - import FreeCADGui - from PySide import QtCore, QtGui - -__title__ = "Path Surface Operation" -__author__ = "sliptonic (Brad Collette)" -__url__ = "http://www.freecadweb.org" - -"""Path surface object and FreeCAD command""" - -# Qt tanslation handling -try: - _encoding = QtGui.QApplication.UnicodeUTF8 - - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig, _encoding) -except AttributeError: - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig) - - -class ObjectStrategy: - - def __init__(self, obj): - obj.addProperty("App::PropertyLinkSubList", "Base", "Path", "The base geometry of this toolpath") - obj.addProperty("App::PropertyBool", "Active", "Path", "Make False, to prevent operation from generating code") - obj.addProperty("App::PropertyString", "Comment", "Path", "An optional comment for this profile") - obj.addProperty("App::PropertyString", "UserLabel", "Path", "User Assigned Label") - - obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", "The library to use to generate the path") - obj.Algorithm = ['OCL Dropcutter', 'OCL Waterline'] - - # Tool Properties - obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", "The tool number in use") - obj.ToolNumber = (0, 0, 1000, 0) - obj.setEditorMode('ToolNumber', 1) # make this read only - obj.addProperty("App::PropertyString", "ToolDescription", "Tool", "The description of the tool ") - obj.setEditorMode('ToolDescription', 1) # make this read onlyt - - # Depth Properties - obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", "The height needed to clear clamps and obstructions") - obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", "Rapid Safety Height between locations.") - obj.addProperty("App::PropertyFloatConstraint", "StepDown", "Depth", "Incremental Step Down of Tool") - obj.StepDown = (0.0, 0.01, 100.0, 0.5) - obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", "Starting Depth of Tool- first cut depth in Z") - obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", "Final Depth of Tool- lowest value in Z") - obj.addProperty("App::PropertyDistance", "FinishDepth", "Depth", "Maximum material removed on final pass.") - - obj.Proxy = self - - def addbase(self, obj, ss, sub=""): - baselist = obj.Base - if len(baselist) == 0: # When adding the first base object, guess at heights - try: - bb = ss.Shape.BoundBox # parent boundbox - subobj = ss.Shape.getElement(sub) - fbb = subobj.BoundBox # feature boundbox - obj.StartDepth = bb.ZMax - obj.ClearanceHeight = bb.ZMax + 5.0 - obj.SafeHeight = bb.ZMax + 3.0 - - if fbb.ZMax < bb.ZMax: - obj.FinalDepth = fbb.ZMax - else: - obj.FinalDepth = bb.ZMin - except: - obj.StartDepth = 5.0 - obj.ClearanceHeight = 10.0 - obj.SafeHeight = 8.0 - - item = (ss, sub) - if item in baselist: - FreeCAD.Console.PrintWarning( - "this object already in the list" + "\n") - else: - baselist.append(item) - obj.Base = baselist - self.execute(obj) - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - def onChanged(self, obj, prop): - return None - - def execute(self, obj): - output = "" - - toolLoad = PathUtils.getLastToolLoad(obj) - if toolLoad is None or toolLoad.ToolNumber == 0: - self.vertFeed = 100 - self.horizFeed = 100 - self.vertRapid = 100 - self.horizRapid = 100 - self.radius = 0.25 - obj.ToolNumber = 0 - obj.ToolDescription = "UNDEFINED" - else: - self.vertFeed = toolLoad.VertFeed.Value - self.horizFeed = toolLoad.HorizFeed.Value - self.vertRapid = toolLoad.VertRapid.Value - self.horizRapid = toolLoad.HorizRapid.Value - tool = PathUtils.getTool(obj, toolLoad.ToolNumber) - if tool.Diameter == 0: - self.radius = 0.25 - else: - self.radius = tool.Diameter/2 - obj.ToolNumber = toolLoad.ToolNumber - obj.ToolDescription = toolLoad.Name - - - output += "(" + obj.Label + ")" - output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")" - - if obj.Active: - path = Path.Path(output) - obj.Path = path - obj.ViewObject.Visibility = True - - else: - path = Path.Path("(inactive operation)") - obj.Path = path - obj.ViewObject.Visibility = False - -class ViewProviderStrategy: - - def __init__(self, obj): # mandatory - # obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property") - obj.Proxy = self - - def __getstate__(self): # mandatory - return None - - def __setstate__(self, state): # mandatory - return None - - def getIcon(self): # optional - return ":/icons/Path-Surfacing.svg" - - def onChanged(self, obj, prop): # optional - # this is executed when a property of the VIEW PROVIDER changes - pass - - def updateData(self, obj, prop): # optional - # this is executed when a property of the APP OBJECT changes - pass - - def setEdit(self, vobj, mode=0): - FreeCADGui.Control.closeDialog() - taskd = TaskPanel() - taskd.obj = vobj.Object - FreeCADGui.Control.showDialog(taskd) - taskd.setupUi() - return True - - def unsetEdit(self, vobj, mode): # optional - # this is executed when the user cancels or terminates edit mode - pass - - -class CommandPathStrategy: - - def GetResources(self): - return {'Pixmap': 'Path-3DSurface', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Strategy", "Strategy"), - 'Accel': "P, D", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Strategy", "Creates a Path Strategy 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): - - ztop = 10 - zbottom = 0 - - FreeCAD.ActiveDocument.openTransaction(translate("Path_Strategy", "Create Strategy")) - FreeCADGui.addModule("PathScripts.PathStrategy") - FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Strategy")') - FreeCADGui.doCommand('PathScripts.PathStrategy.ObjectStrategy(obj)') - FreeCADGui.doCommand('obj.Active = True') - FreeCADGui.doCommand('PathScripts.PathStrategy.ViewProviderStrategy(obj.ViewObject)') - FreeCADGui.doCommand('from PathScripts import PathUtils') - FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 2)) - FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop)) - FreeCADGui.doCommand('obj.SafeHeight = ' + str(ztop + 2)) - FreeCADGui.doCommand('obj.StepDown = ' + str((ztop - zbottom) / 8)) - FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom)) - FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)') - FreeCAD.ActiveDocument.commitTransaction() - - FreeCAD.ActiveDocument.recompute() - FreeCADGui.doCommand('obj.ViewObject.startEditing()') - - -class TaskPanel: - - def __init__(self): - self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/StrategyEdit.ui") - #self.form = FreeCADGui.PySideUic.loadUi(":/panels/SurfaceEdit.ui") - - def accept(self): - self.getFields() - - FreeCADGui.ActiveDocument.resetEdit() - FreeCADGui.Control.closeDialog() - FreeCAD.ActiveDocument.recompute() - FreeCADGui.Selection.removeObserver(self.s) - - def reject(self): - FreeCADGui.Control.closeDialog() - FreeCAD.ActiveDocument.recompute() - FreeCADGui.Selection.removeObserver(self.s) - - def getFields(self): - if self.obj: - if hasattr(self.obj, "StartDepth"): - self.obj.StartDepth = self.form.startDepth.text() - if hasattr(self.obj, "FinalDepth"): - self.obj.FinalDepth = self.form.finalDepth.text() - if hasattr(self.obj, "FinishDepth"): - self.obj.FinishDepth = self.form.finishDepth.text() - if hasattr(self.obj, "StepDown"): - self.obj.StepDown = self.form.stepDown.value() - if hasattr(self.obj, "SafeHeight"): - self.obj.SafeHeight = self.form.safeHeight.text() - if hasattr(self.obj, "ClearanceHeight"): - self.obj.ClearanceHeight = self.form.clearanceHeight.text() - - self.obj.Proxy.execute(self.obj) - - def setFields(self): - self.form.startDepth.setText(str(self.obj.StartDepth.Value)) - self.form.finalDepth.setText(str(self.obj.FinalDepth.Value)) - self.form.finishDepth.setText(str(self.obj.FinishDepth.Value)) - self.form.stepDown.setValue(self.obj.StepDown) - - self.form.safeHeight.setText(str(self.obj.SafeHeight.Value)) - self.form.clearanceHeight.setText(str(self.obj.ClearanceHeight.Value)) - - for i in self.obj.Base: - self.form.baseList.addItem(i[0].Name) - - def open(self): - self.s = SelObserver() - # install the function mode resident - FreeCADGui.Selection.addObserver(self.s) - - def addBase(self): - # check that the selection contains exactly what we want - selection = FreeCADGui.Selection.getSelectionEx() - if len(selection) != 1: - FreeCAD.Console.PrintError(translate( - "PathSurface", "Please select a single solid object from the project tree\n")) - return - - if not len(selection[0].SubObjects) == 0: - FreeCAD.Console.PrintError(translate( - "PathSurface", "Please select a single solid object from the project tree\n")) - return - - sel = selection[0].Object - # get type of object - # if sel.TypeId.startswith('Mesh'): - # # it is a mesh already - # print 'was already mesh' - - # elif sel.TypeId.startswith('Part') and \ - # (sel.Shape.BoundBox.XLength > 0) and \ - # (sel.Shape.BoundBox.YLength > 0) and \ - # (sel.Shape.BoundBox.ZLength > 0): - # print 'this is a solid Part object' - - # else: - # FreeCAD.Console.PrintError( - # translate("PathSurface", "Cannot work with this object\n")) - # return - - self.obj.Proxy.addbase(self.obj, sel) - - self.setFields() # defaults may have changed. Reload. - self.form.baseList.clear() - for i in self.obj.Base: - self.form.baseList.addItem(i[0].Name) - - def deleteBase(self): - dlist = self.form.baseList.selectedItems() - for d in dlist: - newlist = [] - for i in self.obj.Base: - if not i[0].Name == d.text(): - newlist.append(i) - self.obj.Base = newlist - self.form.baseList.takeItem(self.form.baseList.row(d)) - self.obj.Proxy.execute(self.obj) - FreeCAD.ActiveDocument.recompute() - - def itemActivated(self): - FreeCADGui.Selection.clearSelection() - slist = self.form.baseList.selectedItems() - for i in slist: - o = FreeCAD.ActiveDocument.getObject(i.text()) - FreeCADGui.Selection.addSelection(o) - FreeCADGui.updateGui() - - def reorderBase(self): - newlist = [] - for i in range(self.form.baseList.count()): - s = self.form.baseList.item(i).text() - obj = FreeCAD.ActiveDocument.getObject(s) - newlist.append(obj) - self.obj.Base = newlist - self.obj.Proxy.execute(self.obj) - FreeCAD.ActiveDocument.recompute() - - def getStandardButtons(self): - return int(QtGui.QDialogButtonBox.Ok) - - def setupUi(self): - - # Connect Signals and Slots - - #Base Geometry - self.form.addBase.clicked.connect(self.addBase) - self.form.deleteBase.clicked.connect(self.deleteBase) - self.form.reorderBase.clicked.connect(self.reorderBase) - self.form.baseList.itemSelectionChanged.connect(self.itemActivated) - - # Depths - self.form.startDepth.editingFinished.connect(self.getFields) - self.form.finalDepth.editingFinished.connect(self.getFields) - self.form.finishDepth.editingFinished.connect(self.getFields) - self.form.stepDown.editingFinished.connect(self.getFields) - - # Heights - self.form.safeHeight.editingFinished.connect(self.getFields) - self.form.clearanceHeight.editingFinished.connect(self.getFields) - - sel = FreeCADGui.Selection.getSelectionEx() - self.setFields() - - if len(sel) != 0: - self.addBase() - - -class SelObserver: - - def __init__(self): - import PathScripts.PathSelection as PST - PST.surfaceselect() - - def __del__(self): - import PathScripts.PathSelection as PST - PST.clear() - - def addSelection(self, doc, obj, sub, pnt): # Selection object - FreeCADGui.doCommand( - 'Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')') - FreeCADGui.updateGui() - - -if FreeCAD.GuiUp: - # register the FreeCAD command - FreeCADGui.addCommand('Path_Strategy', CommandPathStrategy()) - -FreeCAD.Console.PrintLog("Loading PathStrategy... done\n") diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index aab87893ab..746b4e0716 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -139,7 +139,7 @@ class ToolLibraryManager(): ''' def __init__(self): - self.ToolLibrary = [] + # self.ToolLibrary = [] self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") return @@ -311,20 +311,20 @@ class ToolLibraryManager(): self.saveMainLibrary(tt) return True - def createToolController(self, job, tool): - pass + # def createToolController(self, job, tool): + # pass - def exportListHeeks(self, tooltable): - '''exports one or more Lists as a HeeksCNC tooltable''' - pass + # def exportListHeeks(self, tooltable): + # '''exports one or more Lists as a HeeksCNC tooltable''' + # pass - def exportListLinuxCNC(self, tooltable): - '''exports one or more Lists as a LinuxCNC tooltable''' - pass + # def exportListLinuxCNC(self, tooltable): + # '''exports one or more Lists as a LinuxCNC tooltable''' + # pass - def exportListXML(self, tooltable): - '''exports one or more Lists as an XML file''' - pass + # def exportListXML(self, tooltable): + # '''exports one or more Lists as an XML file''' + # pass class EditorPanel(): def __init__(self): diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 6754f4a7e2..3ad6e43547 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -26,15 +26,13 @@ import FreeCAD import FreeCADGui import Part import math -import Draft -import Path -import TechDraw +# import Path from DraftGeomUtils import geomType -from DraftGeomUtils import findWires -import DraftVecUtils +# from DraftGeomUtils import findWires +# import DraftVecUtils import PathScripts from PathScripts import PathJob -import itertools +# import itertools def cleanedges(splines, precision): '''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths. @@ -88,89 +86,89 @@ def curvetowire(obj, steps): def fmt(val): return format(val, '.4f') -def getProjected(shape,direction): - "returns projected edges from a shape and a direction" - import Part,Drawing - edges = [] - groups = Drawing.projectEx(shape,direction) - for g in groups[0:5]: - if g: - edges.append(g) - # if hasattr(obj,"Tessellation") and obj.Tessellation: - # return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),obj.Tessellation,obj.SegmentLength) - # else: - return Part.makeCompound(edges) +# def getProjected(shape,direction): +# "returns projected edges from a shape and a direction" +# import Part,Drawing +# edges = [] +# groups = Drawing.projectEx(shape,direction) +# for g in groups[0:5]: +# if g: +# edges.append(g) +# # if hasattr(obj,"Tessellation") and obj.Tessellation: +# # return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),obj.Tessellation,obj.SegmentLength) +# # else: +# return Part.makeCompound(edges) -def silhouette(obj): - from FreeCAD import Vector - s = getProjected(obj.Shape, Vector(0,0,1)) - print s - w = TechDraw.findOuterWire(s.Edges) - return w +# def silhouette(obj): +# from FreeCAD import Vector +# s = getProjected(obj.Shape, Vector(0,0,1)) +# print s +# w = TechDraw.findOuterWire(s.Edges) +# return w -def isSameEdge(e1, e2): - """isSameEdge(e1,e2): return True if the 2 edges are both lines or arcs/circles and have the same - points - inspired by Yorik's function isSameLine""" - if not (isinstance(e1.Curve, Part.LineSegment) or isinstance(e1.Curve, Part.Circle)): - return False - if not (isinstance(e2.Curve, Part.LineSegment) or isinstance(e2.Curve, Part.Circle)): - return False - if type(e1.Curve) != type(e2.Curve): - return False - if isinstance(e1.Curve, Part.LineSegment): - if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \ - (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)): - return True - elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \ - (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)): - return True - if isinstance(e1.Curve, Part.Circle): - center = False - radius = False - endpts = False - if e1.Curve.Center == e2.Curve.Center: - center = True - if e1.Curve.Radius == e2.Curve.Radius: - radius = True - if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \ - (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)): - endpts = True - elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \ - (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)): - endpts = True - if (center and radius and endpts): - return True - return False +# def isSameEdge(e1, e2): +# """isSameEdge(e1,e2): return True if the 2 edges are both lines or arcs/circles and have the same +# points - inspired by Yorik's function isSameLine""" +# if not (isinstance(e1.Curve, Part.Line) or isinstance(e1.Curve, Part.Circle)): +# return False +# if not (isinstance(e2.Curve, Part.Line) or isinstance(e2.Curve, Part.Circle)): +# return False +# if type(e1.Curve) != type(e2.Curve): +# return False +# if isinstance(e1.Curve, Part.Line): +# if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \ +# (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)): +# return True +# elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \ +# (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)): +# return True +# if isinstance(e1.Curve, Part.Circle): +# center = False +# radius = False +# endpts = False +# if e1.Curve.Center == e2.Curve.Center: +# center = True +# if e1.Curve.Radius == e2.Curve.Radius: +# radius = True +# if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \ +# (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)): +# endpts = True +# elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \ +# (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)): +# endpts = True +# if (center and radius and endpts): +# return True +# return False def segments(poly): ''' A sequence of (x,y) numeric coordinates pairs ''' return zip(poly, poly[1:] + [poly[0]]) -def is_clockwise(obj): - '''tests if a wire or Path is clockwise''' - sum = 0 - if isinstance(obj, Part.Wire): - for first, second in itertools.izip(obj.Edges, obj.Edges[1:]): - sum = (second.Vertexes[0].X - first.Vertexes[0].X) * (second.Vertexes[0].Y + first.Vertexes[0].Y) - sum += (obj.Edges[0].Vertexes[0].X - obj.Edges[-1].Vertexes[0].X) * (obj.Edges[0].Vertexes[0].Y + obj.Edges[-1].Vertexes[0].Y) - elif isinstance(obj, Path.Path): - movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03'] +# def is_clockwise(obj): +# '''tests if a wire or Path is clockwise''' +# sum = 0 +# if isinstance(obj, Part.Wire): +# for first, second in itertools.izip(obj.Edges, obj.Edges[1:]): +# sum = (second.Vertexes[0].X - first.Vertexes[0].X) * (second.Vertexes[0].Y + first.Vertexes[0].Y) +# sum += (obj.Edges[0].Vertexes[0].X - obj.Edges[-1].Vertexes[0].X) * (obj.Edges[0].Vertexes[0].Y + obj.Edges[-1].Vertexes[0].Y) +# elif isinstance(obj, Path.Path): +# movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03'] - lastLocation = {'Y': 0, 'X': 0, 'Z': 0.0} - currLocation = {'Y': 0, 'X': 0, 'Z': 0.0} - sum = 0 +# lastLocation = {'Y': 0, 'X': 0, 'Z': 0.0} +# currLocation = {'Y': 0, 'X': 0, 'Z': 0.0} +# sum = 0 - for curCommand in obj.Commands: +# for curCommand in obj.Commands: - if curCommand.Name in movecommands: - lastLocation.update(currLocation) - currLocation.update(curCommand.Parameters) - sum += (currLocation["X"] - lastLocation["X"]) * (currLocation["Y"] + lastLocation["Y"]) - sum += (0 - lastLocation["X"]) * (0 + lastLocation["Y"]) +# if curCommand.Name in movecommands: +# lastLocation.update(currLocation) +# currLocation.update(curCommand.Parameters) +# sum += (currLocation["X"] - lastLocation["X"]) * (currLocation["Y"] + lastLocation["Y"]) +# sum += (0 - lastLocation["X"]) * (0 + lastLocation["Y"]) - return sum >= 0 +# return sum >= 0 def loopdetect(obj, edge1, edge2): ''' @@ -192,15 +190,15 @@ def loopdetect(obj, edge1, edge2): return loopwire -def check_clockwise(poly): - ''' - check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise - based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)] - ''' - clockwise = False - if (sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0: - clockwise = not clockwise - return clockwise +# def check_clockwise(poly): +# ''' +# check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise +# based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)] +# ''' +# clockwise = False +# if (sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0: +# clockwise = not clockwise +# return clockwise def filterArcs(arcEdge): @@ -254,235 +252,235 @@ def reverseEdge(e): return newedge -def edge_to_path(lastpt, edge, Z, hf=2.0): - if isinstance(edge.Curve, Part.Circle): - # FreeCAD.Console.PrintMessage("arc\n") - arcstartpt = edge.valueAt(edge.FirstParameter) - midpt = edge.valueAt( - (edge.FirstParameter + edge.LastParameter) * 0.5) - arcendpt = edge.valueAt(edge.LastParameter) - # arcchkpt = edge.valueAt(edge.LastParameter * .99) +# def edge_to_path(lastpt, edge, Z, hf=2.0): +# if isinstance(edge.Curve, Part.Circle): +# # FreeCAD.Console.PrintMessage("arc\n") +# arcstartpt = edge.valueAt(edge.FirstParameter) +# midpt = edge.valueAt( +# (edge.FirstParameter + edge.LastParameter) * 0.5) +# arcendpt = edge.valueAt(edge.LastParameter) +# # arcchkpt = edge.valueAt(edge.LastParameter * .99) - if DraftVecUtils.equals(lastpt, arcstartpt): - startpt = arcstartpt - endpt = arcendpt - else: - startpt = arcendpt - endpt = arcstartpt - center = edge.Curve.Center - relcenter = center.sub(lastpt) - # FreeCAD.Console.PrintMessage("arc startpt= " + str(startpt)+ "\n") - # FreeCAD.Console.PrintMessage("arc midpt= " + str(midpt)+ "\n") - # FreeCAD.Console.PrintMessage("arc endpt= " + str(endpt)+ "\n") - arc_cw = check_clockwise( - [(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)]) - # FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n") - if arc_cw: - output = "G2" - else: - output = "G3" - output += " X" + str(fmt(endpt.x)) + " Y" + \ - str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf) - output += " I" + str(fmt(relcenter.x)) + " J" + \ - str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z)) - output += "\n" - lastpt = endpt - # FreeCAD.Console.PrintMessage("last pt arc= " + str(lastpt)+ "\n") - else: - point = edge.Vertexes[-1].Point - if DraftVecUtils.equals(point, lastpt): # edges can come flipped - point = edge.Vertexes[0].Point - output = "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \ - " Z" + str(fmt(Z)) + " F" + str(hf) + "\n" - lastpt = point - # FreeCAD.Console.PrintMessage("line\n") - # FreeCAD.Console.PrintMessage("last pt line= " + str(lastpt)+ "\n") - return lastpt, output +# if DraftVecUtils.equals(lastpt, arcstartpt): +# startpt = arcstartpt +# endpt = arcendpt +# else: +# startpt = arcendpt +# endpt = arcstartpt +# center = edge.Curve.Center +# relcenter = center.sub(lastpt) +# # FreeCAD.Console.PrintMessage("arc startpt= " + str(startpt)+ "\n") +# # FreeCAD.Console.PrintMessage("arc midpt= " + str(midpt)+ "\n") +# # FreeCAD.Console.PrintMessage("arc endpt= " + str(endpt)+ "\n") +# arc_cw = check_clockwise( +# [(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)]) +# # FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n") +# if arc_cw: +# output = "G2" +# else: +# output = "G3" +# output += " X" + str(fmt(endpt.x)) + " Y" + \ +# str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf) +# output += " I" + str(fmt(relcenter.x)) + " J" + \ +# str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z)) +# output += "\n" +# lastpt = endpt +# # FreeCAD.Console.PrintMessage("last pt arc= " + str(lastpt)+ "\n") +# else: +# point = edge.Vertexes[-1].Point +# if DraftVecUtils.equals(point, lastpt): # edges can come flipped +# point = edge.Vertexes[0].Point +# output = "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \ +# " Z" + str(fmt(Z)) + " F" + str(hf) + "\n" +# lastpt = point +# # FreeCAD.Console.PrintMessage("line\n") +# # FreeCAD.Console.PrintMessage("last pt line= " + str(lastpt)+ "\n") +# return lastpt, output -def convert(toolpath, Z=0.0, PlungeAngle=90.0, Zprevious=None, StopLength=None, vf=1.0, hf=2.0) : - '''convert(toolpath,Z=0.0,vf=1.0,hf=2.0,PlungeAngle=90.0,Zprevious=None,StopLength=None) Converts lines and arcs to G1,G2,G3 moves. Returns a string.''' +# def convert(toolpath, Z=0.0, PlungeAngle=90.0, Zprevious=None, StopLength=None, vf=1.0, hf=2.0) : +# '''convert(toolpath,Z=0.0,vf=1.0,hf=2.0,PlungeAngle=90.0,Zprevious=None,StopLength=None) Converts lines and arcs to G1,G2,G3 moves. Returns a string.''' - if PlungeAngle != 90.0: - if Zprevious is None: - raise Exception("Cannot use PlungeAngle != 90.0 degrees without parameter Zprevious") - tanA = math.tan(math.pi * PlungeAngle / 180.0) - minA = (Zprevious - Z) / sum(edge.Length for edge in toolpath) - if tanA < minA: - tanA = minA - #FreeCAD.Console.PrintMessage('Increasing ramp angle to {0} degrees, to be able to make a full round\n'.format(math.atan(tanA) * 180.0 / math.pi)) - else: - Zprevious = Z +# if PlungeAngle != 90.0: +# if Zprevious is None: +# raise Exception("Cannot use PlungeAngle != 90.0 degrees without parameter Zprevious") +# tanA = math.tan(math.pi * PlungeAngle / 180.0) +# minA = (Zprevious - Z) / sum(edge.Length for edge in toolpath) +# if tanA < minA: +# tanA = minA +# #FreeCAD.Console.PrintMessage('Increasing ramp angle to {0} degrees, to be able to make a full round\n'.format(math.atan(tanA) * 180.0 / math.pi)) +# else: +# Zprevious = Z - lastpt = None - output = "" - path_length = 0.0 - Z_cur = Zprevious +# lastpt = None +# output = "" +# path_length = 0.0 +# Z_cur = Zprevious - # create the path from the offset shape - for edge in toolpath: - if not lastpt: - # set the first point - lastpt = edge.Vertexes[0].Point - # FreeCAD.Console.PrintMessage("last pt= " + str(lastpt)+ "\n") - output += "G1 X" + str(fmt(lastpt.x)) + " Y" + str(fmt(lastpt.y)) + \ - " Z" + str(fmt(Z_cur)) + " F" + str(vf) + "\n" +# # create the path from the offset shape +# for edge in toolpath: +# if not lastpt: +# # set the first point +# lastpt = edge.Vertexes[0].Point +# # FreeCAD.Console.PrintMessage("last pt= " + str(lastpt)+ "\n") +# output += "G1 X" + str(fmt(lastpt.x)) + " Y" + str(fmt(lastpt.y)) + \ +# " Z" + str(fmt(Z_cur)) + " F" + str(vf) + "\n" - if StopLength: - if path_length + edge.Length > StopLength: - # have to split current edge in two - t0 = edge.FirstParameter - t1 = edge.LastParameter - dL = StopLength - path_length - t = t0 + (t1 - t0) * dL / edge.Length - assert(t0 < t < t1) - edge = edge.split(t).Edges[0] - path_length = StopLength - else: - path_length += edge.Length - else: - path_length += edge.Length +# if StopLength: +# if path_length + edge.Length > StopLength: +# # have to split current edge in two +# t0 = edge.FirstParameter +# t1 = edge.LastParameter +# dL = StopLength - path_length +# t = t0 + (t1 - t0) * dL / edge.Length +# assert(t0 < t < t1) +# edge = edge.split(t).Edges[0] +# path_length = StopLength +# else: +# path_length += edge.Length +# else: +# path_length += edge.Length - if Z_cur > Z: - Z_next = Zprevious - path_length * tanA - if Z_next < Z: - # have to split current edge in two - t0 = edge.FirstParameter - t1 = edge.LastParameter - dZ = Z_cur - Z - t = t0 + (t1 - t0) * (dZ / tanA) / edge.Length - assert(t0 < t < t1) - subwire = edge.split(t) - assert(len(subwire.Edges) == 2) - Z_cur = Z - lastpt, codes = edge_to_path(lastpt, subwire.Edges[0], Z_cur, hf) - output += codes - edge = subwire.Edges[1] - else: - Z_cur = Z_next +# if Z_cur > Z: +# Z_next = Zprevious - path_length * tanA +# if Z_next < Z: +# # have to split current edge in two +# t0 = edge.FirstParameter +# t1 = edge.LastParameter +# dZ = Z_cur - Z +# t = t0 + (t1 - t0) * (dZ / tanA) / edge.Length +# assert(t0 < t < t1) +# subwire = edge.split(t) +# assert(len(subwire.Edges) == 2) +# Z_cur = Z +# lastpt, codes = edge_to_path(lastpt, subwire.Edges[0], Z_cur, hf) +# output += codes +# edge = subwire.Edges[1] +# else: +# Z_cur = Z_next - lastpt, codes = edge_to_path(lastpt, edge, Z_cur, hf) - output += codes +# lastpt, codes = edge_to_path(lastpt, edge, Z_cur, hf) +# output += codes - if StopLength: - if path_length >= StopLength: - break +# if StopLength: +# if path_length >= StopLength: +# break - return output +# return output -def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5): - '''SortPath(wire,Side,radius,clockwise,firstedge=None,SegLen =0.5) Sorts the wire and reverses it, if needed. Splits arcs over 180 degrees in two. Returns the reordered offset of the wire. ''' - if firstedge: - edgelist = wire.Edges[:] - if wire.isClosed(): - elindex = None - n = 0 - for e in edgelist: - if isSameEdge(e, firstedge): - # FreeCAD.Console.PrintMessage('found first edge\n') - elindex = n - n = n + 1 - l1 = edgelist[:elindex] - l2 = edgelist[elindex:] - newedgelist = l2 + l1 +# def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5): +# '''SortPath(wire,Side,radius,clockwise,firstedge=None,SegLen =0.5) Sorts the wire and reverses it, if needed. Splits arcs over 180 degrees in two. Returns the reordered offset of the wire. ''' +# if firstedge: +# edgelist = wire.Edges[:] +# if wire.isClosed(): +# elindex = None +# n = 0 +# for e in edgelist: +# if isSameEdge(e, firstedge): +# # FreeCAD.Console.PrintMessage('found first edge\n') +# elindex = n +# n = n + 1 +# l1 = edgelist[:elindex] +# l2 = edgelist[elindex:] +# newedgelist = l2 + l1 - if clockwise: - newedgelist.reverse() - last = newedgelist.pop(-1) - newedgelist.insert(0, last) +# if clockwise: +# newedgelist.reverse() +# last = newedgelist.pop(-1) +# newedgelist.insert(0, last) - preoffset = [] - for e in newedgelist: - if clockwise: - r = reverseEdge(e) - preoffset.append(r) - else: - preoffset.append(e) +# preoffset = [] +# for e in newedgelist: +# if clockwise: +# r = reverseEdge(e) +# preoffset.append(r) +# else: +# preoffset.append(e) - sortedpreoff = Part.__sortEdges__(preoffset) - wire = Part.Wire(sortedpreoff) - #wire = findWires(sortedpreoff)[0] - else: - sortedpreoff = Part.__sortEdges__(edgelist) - wire = Part.Wire(sortedpreoff) - #wire = findWires(sortedpreoff)[0] +# sortedpreoff = Part.__sortEdges__(preoffset) +# wire = Part.Wire(sortedpreoff) +# #wire = findWires(sortedpreoff)[0] +# else: +# sortedpreoff = Part.__sortEdges__(edgelist) +# wire = Part.Wire(sortedpreoff) +# #wire = findWires(sortedpreoff)[0] - edgelist = [] - for e in wire.Edges: - if geomType(e) == "Circle": - arclist = filterArcs(e) - for a in arclist: - edgelist.append(a) - elif geomType(e) == "LineSegment": - edgelist.append(e) - elif geomType(e) == "BSplineCurve" or \ - geomType(e) == "BezierCurve" or \ - geomType(e) == "Ellipse": - edgelist.append(Part.Wire(curvetowire(e, (SegLen)))) - #newwire = Part.Wire(edgelist) - sortededges = Part.__sortEdges__(edgelist) - newwire = findWires(sortededges)[0] +# edgelist = [] +# for e in wire.Edges: +# if geomType(e) == "Circle": +# arclist = filterArcs(e) +# for a in arclist: +# edgelist.append(a) +# elif geomType(e) == "LineSegment": +# edgelist.append(e) +# elif geomType(e) == "BSplineCurve" or \ +# geomType(e) == "BezierCurve" or \ +# geomType(e) == "Ellipse": +# edgelist.append(Part.Wire(curvetowire(e, (SegLen)))) +# #newwire = Part.Wire(edgelist) +# sortededges = Part.__sortEdges__(edgelist) +# newwire = findWires(sortededges)[0] - if is_clockwise(newwire) is not clockwise: - newwire.reverse() +# if is_clockwise(newwire) is not clockwise: +# newwire.reverse() - if Side == 'Left': - # we use the OCC offset feature - offset = newwire.makeOffset(radius) # tool is outside line - elif Side == 'Right': - offset = newwire.makeOffset(-radius) # tool is inside line - else: - if wire.isClosed(): - offset = newwire.makeOffset(0.0) - else: - offset = newwire - offset.reverse() +# if Side == 'Left': +# # we use the OCC offset feature +# offset = newwire.makeOffset(radius) # tool is outside line +# elif Side == 'Right': +# offset = newwire.makeOffset(-radius) # tool is inside line +# else: +# if wire.isClosed(): +# offset = newwire.makeOffset(0.0) +# else: +# offset = newwire +# offset.reverse() - return offset +# return offset -def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart, - ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5, - VertFeed=1.0, HorizFeed=2.0, VertJog=1.0, HorizJog = 2.0, PlungeAngle=90.0): - ''' makes the path - just a simple profile for now ''' - offset = SortPath(wire, Side, radius, clockwise, firstedge, SegLen=SegLen) - if len(offset.Edges) == 0: - return "" +# def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart, +# ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5, +# VertFeed=1.0, HorizFeed=2.0, VertJog=1.0, HorizJog = 2.0, PlungeAngle=90.0): +# ''' makes the path - just a simple profile for now ''' +# offset = SortPath(wire, Side, radius, clockwise, firstedge, SegLen=SegLen) +# if len(offset.Edges) == 0: +# return "" - toolpath = offset.Edges[:] - paths = "" - paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n" - first = toolpath[0].Vertexes[0].Point - paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n" - Zprevious = ZStart - ZCurrent = ZStart - StepDown +# toolpath = offset.Edges[:] +# paths = "" +# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n" +# first = toolpath[0].Vertexes[0].Point +# paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n" +# Zprevious = ZStart +# ZCurrent = ZStart - StepDown - while ZCurrent > ZFinalDepth: - paths += convert(toolpath, Z=ZCurrent, Zprevious=Zprevious, PlungeAngle=PlungeAngle, - vf=VertFeed, hf=HorizFeed) - if not PathClosed: - paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) - paths += "G0 X" + str(fmt(first.x)) + "Y" + \ - str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n" - Zprevious = ZCurrent - ZCurrent = ZCurrent - abs(StepDown) +# while ZCurrent > ZFinalDepth: +# paths += convert(toolpath, Z=ZCurrent, Zprevious=Zprevious, PlungeAngle=PlungeAngle, +# vf=VertFeed, hf=HorizFeed) +# if not PathClosed: +# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) +# paths += "G0 X" + str(fmt(first.x)) + "Y" + \ +# str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n" +# Zprevious = ZCurrent +# ZCurrent = ZCurrent - abs(StepDown) - # do the final Z value - paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, PlungeAngle=PlungeAngle, - vf=VertFeed, hf=HorizFeed) +# # do the final Z value +# paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, PlungeAngle=PlungeAngle, +# vf=VertFeed, hf=HorizFeed) - # when plunging with != 90 degree we have to do one last pass to clear the remaining ramp - if PlungeAngle != 90.0: - tanA = math.tan(math.pi * PlungeAngle / 180.0) - if tanA <= 0.0: - StopLength=None - else: - StopLength=abs(StepDown/tanA) - paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, StopLength=StopLength, - vf=VertFeed, hf=HorizFeed) +# # when plunging with != 90 degree we have to do one last pass to clear the remaining ramp +# if PlungeAngle != 90.0: +# tanA = math.tan(math.pi * PlungeAngle / 180.0) +# if tanA <= 0.0: +# StopLength=None +# else: +# StopLength=abs(StepDown/tanA) +# paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, StopLength=StopLength, +# vf=VertFeed, hf=HorizFeed) - paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n" - return paths +# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n" +# return paths # the next two functions are for automatically populating tool # numbers/height offset numbers based on previously active toolnumbers @@ -548,19 +546,19 @@ def getLastToolLoad(obj): continue return tc -def getToolControllers(obj): - controllers = [] - try: - parent = obj.InList[0] - except: - parent = None +# def getToolControllers(obj): +# controllers = [] +# try: +# parent = obj.InList[0] +# except: +# parent = None - if parent is not None and hasattr(parent, 'Group'): - sibs = parent.Group - for g in sibs: - if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool): - controllers.append(g.Name) - return controllers +# if parent is not None and hasattr(parent, 'Group'): +# sibs = parent.Group +# for g in sibs: +# if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool): +# controllers.append(g.Name) +# return controllers @@ -614,7 +612,6 @@ def addToJob(obj, jobname = None): else: #form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/DlgJobChooser.ui") form = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobChooser.ui") - mylist = [i.Name for i in jobs] form.cboProject.addItems(mylist) r = form.exec_() @@ -629,15 +626,15 @@ def addToJob(obj, jobname = None): job.Group = g return job -def getLastZ(obj): - ''' find the last z value in the job ''' - lastZ = "" - for g in obj.Group: - for c in g.Path.Commands: - for n in c.Parameters: - if n == 'Z': - lastZ = c.Parameters['Z'] - return lastZ +# def getLastZ(obj): +# ''' find the last z value in the job ''' +# lastZ = "" +# for g in obj.Group: +# for c in g.Path.Commands: +# for n in c.Parameters: +# if n == 'Z': +# lastZ = c.Parameters['Z'] +# return lastZ def rapid(x=None, y=None, z=None): """ Returns gcode string to perform a rapid move.""" diff --git a/src/Mod/Path/PathScripts/PostUtils.py b/src/Mod/Path/PathScripts/PostUtils.py index 6377faead5..8d013a862e 100644 --- a/src/Mod/Path/PathScripts/PostUtils.py +++ b/src/Mod/Path/PathScripts/PostUtils.py @@ -33,19 +33,19 @@ FreeCADGui = None if FreeCAD.GuiUp: import FreeCADGui -class OldHighlighter(QtGui.QSyntaxHighlighter): - def highlightBlock(self, text): - myClassFormat = QtGui.QTextCharFormat() - myClassFormat.setFontWeight(QtGui.QFont.Bold) - myClassFormat.setForeground(QtCore.Qt.green) - # the regex pattern to be colored - pattern = "(G.*?|M.*?)\\s" - expression = QtCore.QRegExp(pattern) - index = text.index(expression) - while index >= 0: - length = expression.matchedLength() - setFormat(index, length, myClassFormat) - index = text.index(expression, index + length) +# class OldHighlighter(QtGui.QSyntaxHighlighter): +# def highlightBlock(self, text): +# myClassFormat = QtGui.QTextCharFormat() +# myClassFormat.setFontWeight(QtGui.QFont.Bold) +# myClassFormat.setForeground(QtCore.Qt.green) +# # the regex pattern to be colored +# pattern = "(G.*?|M.*?)\\s" +# expression = QtCore.QRegExp(pattern) +# index = text.index(expression) +# while index >= 0: +# length = expression.matchedLength() +# setFormat(index, length, myClassFormat) +# index = text.index(expression, index + length) @@ -152,7 +152,7 @@ def editor(gcode): '''pops up a handy little editor to look at the code output ''' dia = GCodeEditorDialog() dia.editor.setText(gcode) - result = dia.exec_() + # result = dia.exec_() def fcoms(string,commentsym): ''' filter and rebuild comments with user preferred comment symbol''' diff --git a/src/Mod/Path/PathScripts/ToolAdd.ui b/src/Mod/Path/PathScripts/ToolAdd.ui deleted file mode 100644 index ac93c772ed..0000000000 --- a/src/Mod/Path/PathScripts/ToolAdd.ui +++ /dev/null @@ -1,190 +0,0 @@ - - - Dialog - - - - 0 - 0 - 423 - 435 - - - - Dialog - - - - - - Tool Properties - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Name - - - - - - - - - - Type - - - - - - - - - - Material - - - - - - - - - - Diameter - - - - - - - mm - - - - - - - Length Offset - - - - - - - mm - - - - - - - Flat Radius - - - - - - - mm - - - - - - - Corner Radius - - - - - - - mm - - - - - - - Cutting Edge Angle - - - - - - - ° - - - - - - - Cutting Edge Height - - - - - - - mm - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/Mod/Path/PathScripts/nc/drag_knife.py b/src/Mod/Path/PathScripts/nc/drag_knife.py deleted file mode 100644 index 49a904827a..0000000000 --- a/src/Mod/Path/PathScripts/nc/drag_knife.py +++ /dev/null @@ -1,72 +0,0 @@ -################################################################################ -# drag knife.py -# -# NC code creator for attaching Z coordinates to a surface -# -# Dan Heeks 26th April 2012 - -import recreator -dragging = False -from kurve_funcs import cut_curve as cut_curve -import nc -import area - -################################################################################ -class Creator(recreator.Redirector): - - def __init__(self, original, drag_distance): - recreator.Redirector.__init__(self, original) - - self.drag_distance = drag_distance - self.path = None - - def cut_path(self): - if self.path == None: return - - print self.drag_distance - self.path.OffsetForward(self.drag_distance, False) - - nc.creator = nc.creator.original - - if self.path.getNumVertices() > 0: - v = self.path.FirstVertex() - nc.creator.feed(v.p.x, v.p.y) - - cut_curve(self.path) - nc.creator = self - - self.path = area.Curve() - - def feed(self, x=None, y=None, z=None, a=None, b=None, c=None): - px = self.x - py = self.y - pz = self.z - recreator.Redirector.feed(self, x, y, z, a, b, c) - if self.x == None or self.y == None or self.z == None: - return - if px == self.x and py == self.y: - return - - # add a line to the path - if self.path == None: self.path = area.Curve() - self.path.append(area.Point(self.x, self.y)) - - def arc(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None, ccw = True): - recreator.Redirector.arc(self, x, y, z, i, j, k, r, ccw) - - # add an arc to the path - if self.path == None: self.path = area.Curve() - self.path.append(area.Vertex(1 if ccw else -1, area.Point(self.x, self.y), area.Point(i, j))) - -def drag_begin(drag_distance): - global dragging - if dragging == True: - drag_end() - nc.creator = Creator(nc.creator, drag_distance) - dragging = True - -def drag_end(): - global dragging - nc.creator.cut_path() - nc.creator = nc.creator.original - attached = False diff --git a/src/Mod/Path/PathScripts/nc/makerbotHBP.py b/src/Mod/Path/PathScripts/nc/makerbotHBP.py deleted file mode 100644 index deafb7f231..0000000000 --- a/src/Mod/Path/PathScripts/nc/makerbotHBP.py +++ /dev/null @@ -1,306 +0,0 @@ -import nc -import makerbot_codes as maker -import datetime -import iso_modal -import math - - -now = datetime.datetime.now() - -################################################################################ -class CreatorMakerbotHBP(iso_modal.CreatorIsoModal): - def __init__(self): - iso_modal.CreatorIsoModal.__init__(self) - - self.absolute_flag = True - self.prev_g91 = '' - - -################################################################################ -# program begin and end - - def program_begin(self, id, name=''): - self.write((maker.codes.COMMENT(now))) - self.write((maker.codes.EXTRUDER_TEMP('220')) + (maker.codes.COMMENT('Extruder Temp')) ) - self.write((maker.codes.BUILD_BED_TEMP('110'))+ (maker.codes.COMMENT('Build Bed Temp')) ) - self.write((maker.codes.FAN_OFF()) + (maker.codes.COMMENT('Fan Off')) ) - self.write((maker.codes.METRIC()) + (maker.codes.COMMENT('Metric units')) ) - self.write((maker.codes.ABSOLUTE()) + (maker.codes.COMMENT('Absolute units')) ) - self.write('G92 X0 Y0 Z0 (You are now at 0,0,0)\n') - self.write('G0 Z15 (Move up for warmup)\n') - self.write((maker.codes.EXTRUDER_SPEED_PWM('255')) + (maker.codes.COMMENT('Extruder Speed')) ) - self.write('M6 T0 (Wait for tool to heat up)\n') - self.write('G04 P5000 (Wait 5 seconds)\n') - self.write((maker.codes.EXTRUDER_ON_FWD()) + (maker.codes.COMMENT('Extruder On')) ) - self.write('G04 P5000 (Wait 5 seconds)\n') - self.write((maker.codes.EXTRUDER_OFF()) + (maker.codes.COMMENT('Extruder Off')) ) - self.write('M01 (The heated build platform is heating up. Wait until after the lights have turned off for the first time, clear the test extrusion, and click yes.)\n') - self.write('G0 Z0 (Go back to zero.)\n') - - def program_end(self): - self.write((maker.codes.COMMENT('End of the file. Begin cool-down'))) - self.write((maker.codes.EXTRUDER_TEMP('0')) + (maker.codes.COMMENT('Extruder Temp')) ) - self.write((maker.codes.BUILD_BED_TEMP('0')) + (maker.codes.COMMENT('Build Bed Temp')) ) - self.write((maker.codes.FAN_ON()) + (maker.codes.COMMENT('Fan On')) ) - self.write('G92 Z0 (zero our z axis - hack b/c skeinforge mangles gcodes in end.txt)\n') - self.write('G1 Z10 (go up 10 b/c it was zeroed earlier.)\n') - self.write('G1 X0 Y0 Z10 (go to 0,0,z)\n') - self.write((maker.codes.STEPPERS_OFF()) + (maker.codes.COMMENT('Steppers Off')) ) - - def program_stop(self): - self.write((maker.codes.EXTRUDER_TEMP('0'))) - self.write((maker.codes.BUILD_BED_TEMP('0'))) - self.write((maker.codes.STEPPERS_OFF())) - -################################################################################ -# general - def write_blocknum(self): - pass - - def set_plane(self, plane): - pass - - def workplane(self, id): - pass - - def spindle(self, s, clockwise): - pass -################################################################################ -# Extruder Control - - def extruder_on(self): - self.write((maker.codes.EXTRUDER_ON()) + ('\n')) - - def extruder_off(self): - self.write((maker.codes.EXTRUDER_OFF()) + ('\n')) - - def set_extruder_flowrate(self, flowrate): - self.write((maker.codes.EXTRUDER_SPEED_PWM(flowrate)) + ('\n')) - - def extruder_temp(self, temp): - self.write((maker.codes.EXTRUDER_TEMP(temp)) + ('\n')) - -################################################################################ -# Build Environment Control - def build_bed_temp(self, temp): - self.write((maker.codes.BUILD_BED_TEMP(temp)) + ('\n')) - - def chamber_temp(self, temp): - self.write((maker.codes.CHAMBER_TEMP(temp)) + ('\n')) - -################################################################################ -# Fan Control - def fan_on(self): - self.write((maker.codes.FAN_ON()) + ('\n')) - - def fan_off(self): - self.write((maker.codes.FAN_OFF()) + ('\n')) - -################################################################################ -# Custom routines - - def wipe(self): - self.write(('(This would be a good place for a custom wipe routine)\n')) - -################################################################################ -# APT style INSERT- insert anything into program - - def insert(self, text): - self.write((text + '\n')) - -################################################################################ -# tool info - def tool_change(self, id): - pass - # self.write_blocknum() - # self.write((maker.codes.TOOL() % id) + '\n') - # self.t = id - - def tool_defn(self, id, name='', params=None): - pass -############################################################################ -## Moves - - def rapid(self, x=None, y=None, z=None, a=None, b=None, c=None ): - self.write_blocknum() - if self.g0123_modal: - if self.prev_g0123 != maker.codes.RAPID(): - self.write(maker.codes.RAPID()) - self.prev_g0123 = maker.codes.RAPID() - else: - self.write(maker.codes.RAPID()) - self.write_preps() - if (x != None): - dx = x - self.x - if (self.absolute_flag ): - self.write(maker.codes.X() + (self.fmt % x)) - else: - self.write(maker.codes.X() + (self.fmt % dx)) - self.x = x - if (y != None): - dy = y - self.y - if (self.absolute_flag ): - self.write(maker.codes.Y() + (self.fmt % y)) - else: - self.write(maker.codes.Y() + (self.fmt % dy)) - - self.y = y - if (z != None): - dz = z - self.z - if (self.absolute_flag ): - self.write(maker.codes.Z() + (self.fmt % z)) - else: - self.write(maker.codes.Z() + (self.fmt % dz)) - - self.z = z - - if (a != None): - da = a - self.a - if (self.absolute_flag ): - self.write(maker.codes.A() + (self.fmt % a)) - else: - self.write(maker.codes.A() + (self.fmt % da)) - self.a = a - - if (b != None): - db = b - self.b - if (self.absolute_flag ): - self.write(maker.codes.B() + (self.fmt % b)) - else: - self.write(maker.codes.B() + (self.fmt % db)) - self.b = b - - if (c != None): - dc = c - self.c - if (self.absolute_flag ): - self.write(maker.codes.C() + (self.fmt % c)) - else: - self.write(maker.codes.C() + (self.fmt % dc)) - self.c = c - self.write_spindle() - self.write_misc() - self.write('\n') - - def feed(self, x=None, y=None, z=None, a = None, b = None, c = None): - if self.same_xyz(x, y, z): return - self.write_blocknum() - if self.g0123_modal: - if self.prev_g0123 != maker.codes.FEED(): - self.write(maker.codes.FEED()) - self.prev_g0123 = maker.codes.FEED() - else: - self.write(maker.codes.FEED()) - self.write_preps() - dx = dy = dz = 0 - if (x != None): - dx = x - self.x - if (self.absolute_flag ): - self.write(maker.codes.X() + (self.fmt % x)) - else: - self.write(maker.codes.X() + (self.fmt % dx)) - self.x = x - if (y != None): - dy = y - self.y - if (self.absolute_flag ): - self.write(maker.codes.Y() + (self.fmt % y)) - else: - self.write(maker.codes.Y() + (self.fmt % dy)) - - self.y = y - if (z != None): - dz = z - self.z - if (self.absolute_flag ): - self.write(maker.codes.Z() + (self.fmt % z)) - else: - self.write(maker.codes.Z() + (self.fmt % dz)) - - self.z = z - if (self.fhv) : self.calc_feedrate_hv(math.sqrt(dx*dx+dy*dy), math.fabs(dz)) - self.write_feedrate() - self.write_spindle() - self.write_misc() - self.write('\n') - - def same_xyz(self, x=None, y=None, z=None): - if (x != None): - if (self.fmt % x) != (self.fmt % self.x): - return False - if (y != None): - if (self.fmt % y) != (self.fmt % self.y): - return False - if (z != None): - if (self.fmt % z) != (self.fmt % self.z): - return False - - return True - - def arc(self, cw, x=None, y=None, z=None, i=None, j=None, k=None, r=None): - if self.same_xyz(x, y, z): return - self.write_blocknum() - arc_g_code = '' - if cw: arc_g_code = maker.codes.ARC_CW() - else: arc_g_code = maker.codes.ARC_CCW() - if self.g0123_modal: - if self.prev_g0123 != arc_g_code: - self.write(arc_g_code) - self.prev_g0123 = arc_g_code - else: - self.write(arc_g_code) - self.write_preps() - if (x != None): - dx = x - self.x - if (self.absolute_flag ): - self.write(maker.codes.X() + (self.fmt % x)) - else: - self.write(maker.codes.X() + (self.fmt % dx)) - self.x = x - if (y != None): - dy = y - self.y - if (self.absolute_flag ): - self.write(maker.codes.Y() + (self.fmt % y)) - else: - self.write(maker.codes.Y() + (self.fmt % dy)) - self.y = y - if (z != None): - dz = z - self.z - if (self.absolute_flag ): - self.write(maker.codes.Z() + (self.fmt % z)) - else: - self.write(maker.codes.Z() + (self.fmt % dz)) - self.z = z - if (i != None) : self.write(maker.codes.CENTRE_X() + (self.fmt % i)) - if (j != None) : self.write(maker.codes.CENTRE_Y() + (self.fmt % j)) - if (k != None) : self.write(maker.codes.CENTRE_Z() + (self.fmt % k)) - if (r != None) : self.write(maker.codes.RADIUS() + (self.fmt % r)) -# use horizontal feed rate - if (self.fhv) : self.calc_feedrate_hv(1, 0) - self.write_feedrate() - self.write_spindle() - self.write_misc() - self.write('\n') - - def arc_cw(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None): - self.arc(True, x, y, z, i, j, k, r) - - def arc_ccw(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None): - self.arc(False, x, y, z, i, j, k, r) - - def dwell(self, t): - self.write_blocknum() - self.write_preps() - self.write(maker.codes.DWELL() + (maker.codes.TIME() % t)) - self.write_misc() - self.write('\n') - - def rapid_home(self, x=None, y=None, z=None, a=None, b=None, c=None): - pass - - def rapid_unhome(self): - pass - - def set_machine_coordinates(self): - self.write(maker.codes.MACHINE_COORDINATES()) - self.prev_g0123 = '' - -nc.creator = CreatorMakerbotHBP() - diff --git a/src/Mod/Path/PathScripts/nc/makerbot_codes.py b/src/Mod/Path/PathScripts/nc/makerbot_codes.py deleted file mode 100644 index 50a1f34525..0000000000 --- a/src/Mod/Path/PathScripts/nc/makerbot_codes.py +++ /dev/null @@ -1,128 +0,0 @@ -################################################################################ -# makerbot_codes.py -# -# a lot like iso_codes.py but with reprap/makerbot specific M codes. -# -# Brad Collette, 12th Sept 2010 -# -# Many of these codes have nothing to do with reprap/additive machining but are left here in anticipation of future hybrid machines. - -class Codes(): - def SPACE(self): return(' ') - def FORMAT_FEEDRATE(self): return('%.2f') - def FORMAT_IN(self): return('%.5f') - def FORMAT_MM(self): return('%.3f') - def FORMAT_ANG(self): return('%.1f') - def FORMAT_TIME(self): return('%.2f') - def FORMAT_DWELL(self): return('P%f') - - def BLOCK(self): return('N%i' + self.SPACE()) - def COMMENT(self,comment): return( (' (%s)\n' % comment ) ) - def VARIABLE(self): return( '#%i') - def VARIABLE_SET(self): return( '=%.3f') - - def PROGRAM(self): return( 'O%i') - def PROGRAM_END(self): return( 'M02') - - def SUBPROG_CALL(self): return( 'M98' + self.SPACE() + 'P%i') - def SUBPROG_END(self): return( 'M99') - - def STOP_OPTIONAL(self): return('M01') - def STOP(self): return('M00') - - def IMPERIAL(self): return(self.SPACE() + 'G20') - def METRIC(self): return(self.SPACE() + 'G21' + self.SPACE()) - def ABSOLUTE(self): return(self.SPACE() + 'G90' + self.SPACE()) - def INCREMENTAL(self): return(self.SPACE() + 'G91') - def SET_TEMPORARY_COORDINATE_SYSTEM(self): return('G92' + self.SPACE()) - def REMOVE_TEMPORARY_COORDINATE_SYSTEM(self): return('G92.1' + self.SPACE()) - def POLAR_ON(self): return(self.SPACE() + 'G16') - def POLAR_OFF(self): return(self.SPACE() + 'G15') - def PLANE_XY(self): return(self.SPACE() + 'G17') - def PLANE_XZ(self): return(self.SPACE() + 'G18') - def PLANE_YZ(self): return(self.SPACE() + 'G19') - - def TOOL(self): return(self.SPACE() +'T%i') - def TOOL_DEFINITION(self): return('G10' + self.SPACE() + 'L1' + self.SPACE()) - - def WORKPLANE(self): return('G%i') - def WORKPLANE_BASE(self): return(53) - - def FEEDRATE(self): return((self.SPACE() + ' F')) - def SPINDLE(self, format, speed): return(self.SPACE() + 'S' + (format % speed)) - def SPINDLE_CW(self): return(self.SPACE() + 'M03') - def SPINDLE_CCW(self): return(self.SPACE() + 'M04') - def COOLANT_OFF(self): return(self.SPACE() + 'M09') - def COOLANT_MIST(self): return(self.SPACE() + 'M07') - def COOLANT_FLOOD(self): return(self.SPACE() + 'M08') - def GEAR_OFF(self): return(self.SPACE() + '?') - def GEAR(self): return('M%i') - def GEAR_BASE(self): return(37) - - def RAPID(self): return('G0') - def FEED(self): return('G1') - def ARC_CW(self): return('G2') - def ARC_CCW(self): return('G3') - def DWELL(self): return('G04') - def DRILL(self): return(self.SPACE() + 'G81') - def DRILL_WITH_DWELL(self, format, dwell): return(self.SPACE() + 'G82' + (format % dwell)) - def PECK_DRILL(self): return(self.SPACE() + 'G83') - def PECK_DEPTH(self, format, depth): return(self.SPACE() + 'Q' + (format % depth)) - def RETRACT(self, format, height): return(self.SPACE() + 'R' + (format % height)) - def END_CANNED_CYCLE(self): return(self.SPACE() + 'G80') - - def X(self): return(self.SPACE() + 'X') - def Y(self): return(self.SPACE() + 'Y') - def Z(self): return(self.SPACE() + 'Z') - def A(self): return(self.SPACE() + 'A') - def B(self): return(self.SPACE() + 'B') - def C(self): return(self.SPACE() + 'C') - def CENTRE_X(self): return(self.SPACE() + 'I') - def CENTRE_Y(self): return(self.SPACE() + 'J') - def CENTRE_Z(self): return(self.SPACE() + 'K') - def RADIUS(self): return(self.SPACE() + 'R') - def TIME(self): return(self.SPACE() + 'P') - - def PROBE_TOWARDS_WITH_SIGNAL(self): return('G38.2' + self.SPACE()) - def PROBE_TOWARDS_WITHOUT_SIGNAL(self): return('G38.3' + self.SPACE()) - def PROBE_AWAY_WITH_SIGNAL(self): return('G38.4' + self.SPACE()) - def PROBE_AWAY_WITHOUT_SIGNAL(self): return('G38.5' + self.SPACE()) - - def MACHINE_COORDINATES(self): return('G53' + self.SPACE()) - - def EXTRUDER_ON (self): return('M101') #deprecated - def EXTRUDER_OFF (self): return('M103') - def EXTRUDER_TEMP (self, degree_celsius): return('M104 S' + '%s' % degree_celsius) - def EXTRUDER_TEMP_WAIT (self, degree_celsius): return('M109 S' + '%s' % degree_celsius) - def READ_EXTRUDER_TEMP (self): return('M105') - def EXTRUDER_SPEED_PWM (self, speed_in_PWM): return('M108 S' + '%s' % speed_in_PWM) #deprecated - def EXTRUDER_SPEED_RPM (self, speed_in_RPM): return('M108 P' + '%s' % speed_in_RPM) #deprecated - - def STEPPERS_OFF(self): return(self.SPACE() + 'M118') - - def ALL_WAIT (self): return(self.SPACE() + 'M116') # Wait for all temperature and slow-changing variables to reach set values - - def FAN_ON (self): return(self.SPACE() + 'M106') - def FAN_OFF (self): return(self.SPACE() + 'M107') - - def VALVE_OPEN (self, delay): return(self.SPACE() + ('M126 P' + '%' % delay) ) - def VALVE_CLOSE (self, delay): return(self.SPACE() + ('M127 P' + '%' % delay) ) - - def BUILD_BED_TEMP (self, degree_celsius): return('M140 S' + '%s' % degree_celsius) - def BED_HOLDING_PRESSURE (self, pressure): return('M142 S' + '%s' % pressure) - - def CHAMBER_TEMP (self, degree_celsius): return('M141 S' + '%s' % degree_celsius) - -#The following codes are listed on the reprap wiki page at http://reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes but require more study. -# -#G28 G Y Xnnn Ynnn Znnn Move to origin (on specified axes only, if X/Y/Z parameters are present) -#M105 M N none Request current extruder and base temperatures (in Celsius) -#M110 M N none Set current line number to Nxxx value preceeding command -#M111 M N Snnn Set debug level bitfield to value of parameter (default 6) -#M112 M N none Emergency stop (stop immediately, discarding any buffered commands) -#M113 M N Snnn Set Extruder PWM (to value defined by pot, or to parameter value if present) -#M114 M N none Get Current Position (return current X, Y, Z and E values) -#M117 M N none Get Zero Position (return X, Y, Z and E values of endstop hits) - - -codes = Codes() diff --git a/src/Mod/Path/PathScripts/nc/printbot3d.py b/src/Mod/Path/PathScripts/nc/printbot3d.py deleted file mode 100644 index 3ea45867fb..0000000000 --- a/src/Mod/Path/PathScripts/nc/printbot3d.py +++ /dev/null @@ -1,53 +0,0 @@ -################################################################################ -# printbot3d.py -# -# Dan Heeks 18th October 2010 - -import nc -import iso_modal -import math - -################################################################################ -class CreatorPrintbot(iso_modal.CreatorIsoModal): - - def __init__(self): - iso_modal.CreatorIsoModal.__init__(self) - - def tool_defn(self, id, name='', params=None): - pass - - def write_blocknum(self): - pass - - def set_plane(self, plane): - pass - - def workplane(self, id): - pass - -# Extruder Control - - def extruder_on(self): - self.write('M101\n') - - def extruder_off(self): - self.write('M103\n') - - def set_extruder_flowrate(self, flowrate): - # re-use the spindle speed function - self.spindle(flowrate, True) - - def extruder_temp(self, temp): - self.write((maker.codes.EXTRUDER_TEMP(temp)) + ('\n')) - -# General - def rapid(x=None, y=None, z=None, a=None, b=None, c=None): - # do a G1 even for rapid moves - iso_modal.CreatorIsoModal.feed(self, x, y, z) - - def feed(self, x=None, y=None, z=None, a = None, b = None, c = None): - iso_modal.CreatorIsoModal.feed(self, x, y, z) - -################################################################################ - -nc.creator = CreatorPrintbot() diff --git a/src/Mod/Path/PathScripts/nc/printbot3d_read.py b/src/Mod/Path/PathScripts/nc/printbot3d_read.py deleted file mode 100644 index 4cdc6ce6ca..0000000000 --- a/src/Mod/Path/PathScripts/nc/printbot3d_read.py +++ /dev/null @@ -1,17 +0,0 @@ -import iso_read as iso -import sys - -# based on the iso reader - -class Parser(iso.Parser): - def __init__(self, writer): - iso.Parser.__init__(self, writer) - - def ParseWord(self, word): - iso.Parser.ParseWord(self, word) - if (word == 'M103'): - self.path_col = "rapid" - self.col = "rapid" - elif (word == 'M101'): - self.path_col = "feed" - self.col = "feed" diff --git a/src/Mod/Path/PathScripts/toollibrarymanager.py b/src/Mod/Path/PathScripts/toollibrarymanager.py deleted file mode 100644 index f161758bc6..0000000000 --- a/src/Mod/Path/PathScripts/toollibrarymanager.py +++ /dev/null @@ -1,242 +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 * -# * * -# *************************************************************************** - -import FreeCAD -import xml.sax -import FreeCADGui -import Path -import Draft -import Part -import os - -from PySide import QtCore, QtGui - -try: - _encoding = QtGui.QApplication.UnicodeUTF8 - - def _translate(context, text, disambig): - return QtGui.QApplication.translate(context, text, disambig, _encoding) -except AttributeError: - def _translate(context, text, disambig): - return QtGui.QApplication.translate(context, text, disambig) - - -# Tooltable XML readers - -class FreeCADTooltableHandler(xml.sax.ContentHandler): - # http://www.tutorialspoint.com/python/python_xml_processing.htm - - def __init__(self): - self.tooltable = None - self.tool = None - self.number = None - - # Call when an element is found - def startElement(self, tag, attributes): - if tag == "Tooltable": - self.tooltable = Path.Tooltable() - elif tag == "Toolslot": - self.number = int(attributes["number"]) - elif tag == "Tool": - self.tool = Path.Tool() - self.tool.Name = str(attributes["name"]) - self.tool.ToolType = str(attributes["type"]) - self.tool.Material = str(attributes["mat"]) - # for some reason without the following line I get an error - print attributes["diameter"] - self.tool.Diameter = float(attributes["diameter"]) - self.tool.LengthOffset = float(attributes["length"]) - self.tool.FlatRadius = float(attributes["flat"]) - self.tool.CornerRadius = float(attributes["corner"]) - self.tool.CuttingEdgeAngle = float(attributes["angle"]) - self.tool.CuttingEdgeHeight = float(attributes["height"]) - - # Call when an elements ends - def endElement(self, tag): - if tag == "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): - self.tooltable = Path.Tooltable() - self.tool = None - self.number = None - - # Call when an element is found - def startElement(self, tag, attributes): - if tag == "Tool": - self.tool = Path.Tool() - self.number = int(attributes["tool_number"]) - self.tool.Name = str(attributes["title"]) - elif tag == "params": - t = str(attributes["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(attributes["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 attributes["diameter"] - self.tool.Diameter = float(attributes["diameter"]) - self.tool.LengthOffset = float(attributes["tool_length_offset"]) - self.tool.FlatRadius = float(attributes["flat_radius"]) - self.tool.CornerRadius = float(attributes["corner_radius"]) - self.tool.CuttingEdgeAngle = float( - attributes["cutting_edge_angle"]) - self.tool.CuttingEdgeHeight = float( - attributes["cutting_edge_height"]) - - # Call when an elements ends - def endElement(self, tag): - if tag == "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 - ''' - - def __init__(self): - self.ToolLibrary = [] - self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path/ToolLibrary") - return - - def saveLibrary(self): - '''Persists the entire library to FreeCAD user preferences''' - tmpstring = "" - for table in self.ToolLibrary: - if table["listtype"] == 'User': - tmpstring += table["list"].Content - self.prefs.SetString("ToolLibrary", tmpstring) - - # FreeCAD.ConfigSet("PathToolTable:" + table[0], table[2].Content) - - def loadLibrary(self): - '''Loads the current library from FreeCAD user preferences''' - # Get persisted libraries from user prefs - tmpstring = self.prefs.GetString("ToolLibrary", "") - ToolLibrary = [] - if tmpstring != "": - Handler = FreeCADTooltableHandler() - try: - xml.sax.parseString(tmpstring, Handler) - tt = Handler.tooltable - toollist = {'name': "main", 'listtype': "User", 'list': tt} - ToolLibrary.append(toollist) - except: - FreeCAD.Console.PrintError( - "Unable to import tools from user preferences") - - # Get ToolTables from any open CNC jobs - for o in FreeCAD.ActiveDocument.Objects: - if "Proxy" in o.PropertiesList: - if hasattr(o, "Tooltable"): - toollist = {'name': o.Name, - 'listtype': "Job", 'list': o.Tooltable} - ToolLibrary.append(toollist) - self.ToolLibrary = ToolLibrary - return self.ToolLibrary - - # methods for lists - def addList(self, tablename, listtype="User", TL=None): - '''Add a new tooltable to the user library''' - if TL is None: - TL = Path.Tooltable() - toollist = {'name': tablename, 'listtype': listtype, 'list': TL} - self.ToolLibrary.append(toollist) - return TL - - def deleteList(self, tablename): - '''Delete all lists from the user library with the given listname''' - for l in self.ToolLibrary: - if l['name'] == tablename: - # maybe check if tools exist in list - self.ToolLibrary.remove(l) - return - - def findList(self, tablename): - '''Finds and returns list by name''' - returnlist = [] - for l in self.ToolLibrary: - if l['name'] == tablename: - returnlist.append(l) - return returnlist - - # methods for importing and exporting - def read(self): - "imports a tooltable from a file" - filename = QtGui.QFileDialog.getOpenFileName(None, _translate("ToolLibraryManager", "Import tooltable", None), None, _translate( - "ToolLibraryManager", "Tooltable XML (*.xml);;HeeksCAD tooltable (*.tooltable)", None)) - if filename: - parser = xml.sax.make_parser() - parser.setFeature(xml.sax.handler.feature_namespaces, 0) - if os.path.splitext(filename[0])[1].lower() == ".tooltable": - Handler = HeeksTooltableHandler() - else: - Handler = FreeCADTooltableHandler() - parser.setContentHandler(Handler) - parser.parse(str(filename[0])) - if Handler.tooltable: - self.addList(filename[0], Handler.tooltable) - # self.reset() - - def createToolController(self, job, tool): - pass - - def exportListHeeks(self, tooltable): - '''exports one or more Lists as a HeeksCNC tooltable''' - pass - - def exportListLinuxCNC(self, tooltable): - '''exports one or more Lists as a LinuxCNC tooltable''' - pass - - def exportListXML(self, tooltable): - '''exports one or more Lists as an XML file''' - pass From 9507fa6cae8698d1785924d336c88ffa779a006f Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sat, 3 Dec 2016 14:37:21 -0600 Subject: [PATCH 05/11] PATH: improved stepdown calculation and test --- src/Mod/Path/PathScripts/PathUtils.py | 63 +++++-- src/Mod/Path/PathTests/TestPathDepthParams.py | 163 ++++++++++++++++++ src/Mod/Path/TestPathApp.py | 4 +- 3 files changed, 210 insertions(+), 20 deletions(-) create mode 100644 src/Mod/Path/PathTests/TestPathDepthParams.py diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 3ad6e43547..2f6763b4df 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -26,7 +26,9 @@ import FreeCAD import FreeCADGui import Part import math +# import Draft # import Path +# import TechDraw from DraftGeomUtils import geomType # from DraftGeomUtils import findWires # import DraftVecUtils @@ -103,7 +105,6 @@ def fmt(val): return format(val, '.4f') # def silhouette(obj): # from FreeCAD import Vector # s = getProjected(obj.Shape, Vector(0,0,1)) -# print s # w = TechDraw.findOuterWire(s.Edges) # return w @@ -808,34 +809,58 @@ def rampPlunge(edge, rampangle, destZ, startZ): class depth_params: - '''calculates the intermediate depth values for various operations given the starting, ending, and stepdown parameters''' + '''calculates the intermediate depth values for various operations given the starting, ending, and stepdown parameters + (self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_depth, final_depth, [user_depths=None]) + + Note: if user_depths are supplied, only user_depths will be used. + + clearance_height: Height to clear all obstacles + rapid_safety_space: Height to rapid between locations + start_depth: Top of Stock + step_down: Distance to step down between passes (always positive) + z_finish_step: Maximum amount of material to remove on the final pass + final_depth: Lowest point of the cutting operation + user_depths: List of specified depths + ''' + + def __init__(self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths=None): + '''self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_depth, final_depth, [user_depths=None]''' + if z_finish_step > step_down: + raise ValueError('z_finish_step must be less than step_down') - def __init__(self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_depth, final_depth, user_depths=None): self.clearance_height = clearance_height self.rapid_safety_space = math.fabs(rapid_safety_space) self.start_depth = start_depth self.step_down = math.fabs(step_down) - self.z_finish_depth = math.fabs(z_finish_depth) + self.z_finish_step = math.fabs(z_finish_step) self.final_depth = final_depth self.user_depths = user_depths - def get_depths(self): + def get_depths(self, equalstep=False): + '''returns a list of depths to be used in order from first to last. + equalstep=True: all steps down before the finish pass will be equalized.''' + depths = [] if self.user_depths is not None: depths = self.user_depths else: - depth = self.final_depth - depths = [depth] - depth += self.z_finish_depth - if depth + 0.0000001 < self.start_depth: - if self.z_finish_depth > 0.0000001: - depths.insert(0, depth) - layer_count = int((self.start_depth - depth) / - self.step_down - 0.0000001) + 1 - if layer_count > 0: - layer_depth = (self.start_depth - depth) / layer_count - for i in range(1, layer_count): - depth += layer_depth - depths.append(depth) - depths.reverse() + total_depth = self.start_depth - self.final_depth + if total_depth <= 0: + return depths + layers_required = int((total_depth - self.z_finish_step) / self.step_down) + partial_steplayer = (total_depth - self.z_finish_step) % self.step_down + if equalstep is True and partial_steplayer > 0: + layerstep = float((total_depth - self.z_finish_step) / (layers_required + 1)) + else: + layerstep = self.step_down + + for step in range(layers_required): + d = self.start_depth - ((step +1) * layerstep) + depths.append(d) + + if self.z_finish_step != 0 and depths[-1] != self.final_depth + self.z_finish_step: + depths.append(self.final_depth + self.z_finish_step) + if depths[-1] != self.final_depth: + depths.append(self.final_depth) + return depths diff --git a/src/Mod/Path/PathTests/TestPathDepthParams.py b/src/Mod/Path/PathTests/TestPathDepthParams.py new file mode 100644 index 0000000000..244bb700eb --- /dev/null +++ b/src/Mod/Path/PathTests/TestPathDepthParams.py @@ -0,0 +1,163 @@ +# -*- 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 * +# * * +# *************************************************************************** + +import PathScripts.PathUtils as PU +import unittest + + +class depthTestCases(unittest.TestCase): + def test00(self): + '''Stepping down to zero ''' + clearance_height= 15 + rapid_safety_space = 12 + + start_depth = 10 + step_down = 2 + z_finish_step = 1 + final_depth = 0 + user_depths = None + + expected =[8,6,4,2,1,0] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths() + self.assertListEqual (r, expected) + + def test10(self): + '''Stepping from zero to a negative depth ''' + + clearance_height= 10 + rapid_safety_space = 5 + + start_depth = 0 + step_down = 2 + z_finish_step = 0 + final_depth = -10 + user_depths = None + + expected =[-2, -4, -6, -8, -10] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths() + self.assertListEqual (r, expected) + + def test20(self): + '''Start and end are equal or start lower than finish ''' + clearance_height= 15 + rapid_safety_space = 12 + + start_depth = 10 + step_down = 2 + z_finish_step = 0 + final_depth = 10 + user_depths = None + + expected =[] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths() + self.assertListEqual (r, expected) + + start_depth = 10 + final_depth = 15 + + expected =[] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths() + self.assertListEqual (r, expected) + + + + + def test30(self): + '''User Parameters passed in''' + clearance_height= 10 + rapid_safety_space = 5 + + start_depth = 0 + step_down = 2 + z_finish_step = 0 + final_depth = -10 + user_depths = [2, 4, 8, 10, 11, 12] + + expected =[2, 4, 8, 10, 11, 12] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths() + self.assertListEqual (r, expected) + + def test40(self): + '''Finish depth passed in.''' + clearance_height= 10 + rapid_safety_space = 5 + + start_depth = 0 + step_down = 2 + z_finish_step = 1 + final_depth = -10 + user_depths = None + + expected =[-2, -4, -6, -8, -9, -10] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths() + self.assertListEqual (r, expected) + + + def test50(self): + '''stepping down with equalstep=True''' + clearance_height= 10 + rapid_safety_space = 5 + + start_depth = 10 + step_down = 3 + z_finish_step = 0 + final_depth = 0 + user_depths = None + + expected =[7.5, 5.0, 2.5, 0] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths(equalstep=True) + self.assertListEqual (r, expected) + + + def test60(self): + '''stepping down with equalstep=True and a finish depth''' + clearance_height= 10 + rapid_safety_space = 5 + + start_depth = 10 + step_down = 3 + z_finish_step = 1 + final_depth = 0 + user_depths = None + + expected =[7.0, 4.0, 1.0, 0] + + d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths) + r = d.get_depths(equalstep=True) + self.assertListEqual (r, expected) + diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 5f246e8c7e..82174b3bf3 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -26,4 +26,6 @@ import TestApp from PathTests.TestPathPost import PathPostTestCases -from PathTests.TestPathGeom import TestPathGeom +#from PathTests.TestPathGeom import TestPathGeom +from PathTests.TestPathDepthParams import depthTestCases + From e35377298f46dbf5a4c5a40a56ba5b0f7d1694ca Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sat, 3 Dec 2016 14:37:50 -0600 Subject: [PATCH 06/11] PATH: Default values for start/end depths improved --- src/Mod/Path/PathScripts/PathMillFace.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/PathScripts/PathMillFace.py index 80f11320e3..d27c1adf5c 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/PathScripts/PathMillFace.py @@ -114,12 +114,12 @@ class ObjectFace: bb = ss.Shape.BoundBox # parent boundbox subobj = ss.Shape.getElement(sub) fbb = subobj.BoundBox # feature boundbox - obj.StartDepth = bb.ZMax + obj.StartDepth = bb.ZMax + 1 obj.ClearanceHeight = bb.ZMax + 5.0 obj.SafeHeight = bb.ZMax + 3.0 if fbb.ZMax == fbb.ZMin and fbb.ZMax == bb.ZMax: # top face - obj.FinalDepth = bb.ZMin + obj.FinalDepth = fbb.ZMin elif fbb.ZMax > fbb.ZMin and fbb.ZMax == bb.ZMax: # vertical face, full cut obj.FinalDepth = fbb.ZMin elif fbb.ZMax > fbb.ZMin and fbb.ZMin > bb.ZMin: # internal vertical wall @@ -211,6 +211,7 @@ class ObjectFace: # To reload this from FreeCAD, use: import PathScripts.PathFace; reload(PathScripts.PathFace) def execute(self, obj): + print "in execute" if not obj.Active: path = Path.Path("(inactive operation)") @@ -511,6 +512,8 @@ class TaskPanel: for i in self.obj.Base: for sub in i[1]: self.form.baseList.addItem(i[0].Name + "." + sub) + #self.obj.Proxy.execute(self.obj) + FreeCAD.ActiveDocument.recompute() def deleteBase(self): dlist = self.form.baseList.selectedItems() @@ -533,11 +536,10 @@ class TaskPanel: newlist.append(i) self.form.baseList.takeItem(self.form.baseList.row(d)) self.obj.Base = newlist - self.obj.Proxy.execute(self.obj) + #self.obj.Proxy.execute(self.obj) FreeCAD.ActiveDocument.recompute() def itemActivated(self): - print self.form.baseList.selectedItems()[0].text() FreeCADGui.Selection.clearSelection() slist = self.form.baseList.selectedItems() for i in slist: @@ -561,7 +563,7 @@ class TaskPanel: newlist.append(item) self.obj.Base = newlist - self.obj.Proxy.execute(self.obj) + #self.obj.Proxy.execute(self.obj) FreeCAD.ActiveDocument.recompute() def getStandardButtons(self): From f02e7b1eae074d15b1298a4f42c0a96768a88b63 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sat, 19 Nov 2016 17:05:41 -0600 Subject: [PATCH 07/11] PATH: Prevent Job creation without Base object. PathMillFace won't add a base if it isn't known to the parent --- src/Mod/Path/PathScripts/PathJob.py | 3 +++ src/Mod/Path/PathScripts/PathMillFace.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index 27ee74515d..12bee9bd77 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -243,6 +243,9 @@ class TaskPanel: self.postProcessorArgsDefaultTooltip = self.form.cboPostProcessorArgs.toolTip() def accept(self): + if self.obj.Base is None: + QtGui.QMessageBox.information(None,"","No Base Object Selected.") + return self.getFields() FreeCADGui.ActiveDocument.resetEdit() FreeCADGui.Control.closeDialog() diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/PathScripts/PathMillFace.py index d27c1adf5c..3692ced048 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/PathScripts/PathMillFace.py @@ -27,6 +27,7 @@ import Path from PySide import QtCore, QtGui from PathScripts import PathUtils import Part +import PathScripts.PathUtils import PathScripts.PathKurveUtils import area import TechDraw @@ -135,6 +136,10 @@ class ObjectFace: def addFacebase(self, obj, ss, sub=""): + parent = PathScripts.PathUtils.findParentJob(obj) + if parent.Base is None: + return + baselist = obj.Base if baselist is None: baselist = [] From b1d46c6538ef57795a8efa0612d0be1366d1f95a Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sun, 20 Nov 2016 13:55:49 -0600 Subject: [PATCH 08/11] PATH: Drilling: allow selection of partial circular edges --- src/Mod/Path/PathScripts/PathDrilling.py | 38 ++++++++++++++++++++--- src/Mod/Path/PathScripts/PathJob.py | 3 -- src/Mod/Path/PathScripts/PathSelection.py | 2 +- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathDrilling.py b/src/Mod/Path/PathScripts/PathDrilling.py index 37f86aa14d..ccdec749b8 100644 --- a/src/Mod/Path/PathScripts/PathDrilling.py +++ b/src/Mod/Path/PathScripts/PathDrilling.py @@ -195,7 +195,7 @@ class ObjectDrilling: if isinstance(subobj.Edges[0].Curve, Part.Circle): drillable = True if str(subobj.Surface) == "": - drillable = True + drillable = subobj.isClosed() if len(subobj.Edges) == 3: cedge = [] ledge = [] @@ -211,7 +211,7 @@ class ObjectDrilling: drillable = False if sub[0:4] == 'Edge': o = obj.getElement(sub) - if isinstance(o.Curve, Part.Circle) and len(o.Vertexes) == 1: + if isinstance(o.Curve, Part.Circle): drillable = True return drillable @@ -266,9 +266,37 @@ class ObjectDrilling: FreeCAD.Console.PrintWarning("Drillable location already in the list" + "\n") else: baselist.append(item) - print baselist - obj.Base = baselist - self.execute(obj) + + if sub[0:4] == 'Edge': + drillableEdges = [] + o = ss.Shape.getElement(sub) + + for i in range(len(ss.Shape.Edges)): + candidateedge = ss.Shape.getElement("Edge" + str(i+1)) + if self.checkdrillable(ss.Shape, "Edge" + str(i+1)): + if candidateedge.Curve.Radius == o.Curve.Radius and candidateedge.Curve.Center.z == o.Curve.Center.z: + drillableEdges.append("Edge" + str(i+1)) + if len(drillableEdges) > 1: + reply = QtGui.QMessageBox.question(None,"","Multiple drillable faces found. Drill them all?", + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.Yes: + for i in drillableEdges: + if i in baselist: + FreeCAD.Console.PrintWarning("Drillable location already in the list" + "\n") + continue + else: + newitem = (ss, i) + baselist.append(newitem) + else: + if item in baselist: + FreeCAD.Console.PrintWarning("Drillable location already in the list" + "\n") + else: + baselist.append(item) + + print baselist + obj.Base = baselist + self.execute(obj) + class _ViewProviderDrill: def __init__(self, obj): diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index 12bee9bd77..c22e657ed7 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -332,11 +332,8 @@ class TaskPanel: else: for o in FreeCADGui.Selection.getCompleteSelection(): baseindex = self.form.cboBaseObject.findText(o.Name, QtCore.Qt.MatchFixedString) - print baseindex if baseindex >= 0: - self.form.cboBaseObject.blockSignals(True) self.form.cboBaseObject.setCurrentIndex(baseindex) - self.form.cboBaseObject.blockSignals(False) def open(self): diff --git a/src/Mod/Path/PathScripts/PathSelection.py b/src/Mod/Path/PathScripts/PathSelection.py index 3fa24b653e..78bd7af7d1 100644 --- a/src/Mod/Path/PathScripts/PathSelection.py +++ b/src/Mod/Path/PathScripts/PathSelection.py @@ -105,7 +105,7 @@ class DRILLGate: subobj = obj.getElement(sub) drillable = isinstance(subobj.Edges[0].Curve, Part.Circle) if str(subobj.Surface) == "": - drillable = True + drillable = subobj.isClosed() if sub[0:4] == 'Edge': o = obj.getElement(sub) From 92c2dce16d1645228cbbd4c4d6964fb3453623fb Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sat, 3 Dec 2016 15:06:15 -0600 Subject: [PATCH 09/11] PATH: More reasonble defaults for new tools --- src/Mod/Path/CMakeLists.txt | 101 +++++++++--------- src/Mod/Path/Gui/Resources/panels/ToolEdit.ui | 28 ++++- .../PathScripts/PathToolLibraryManager.py | 4 +- 3 files changed, 77 insertions(+), 56 deletions(-) diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 487f68d0f7..2eb3a902e7 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -16,67 +16,66 @@ INSTALL( SET(PathScripts_SRCS PathCommands.py - PathScripts/DogboneDressup.py - PathScripts/DragknifeDressup.py - PathScripts/PathAreaUtils.py - PathScripts/PathArray.py - PathScripts/PathComment.py - PathScripts/PathCompoundExtended.py + PathScripts/__init__.py + PathScripts/PostUtils.py + PathScripts/example_pre.py + PathScripts/opensbp_pre.py + PathScripts/opensbp_post.py + PathScripts/example_post.py + PathScripts/linuxcnc_post.py + PathScripts/centroid_post.py + PathScripts/comparams_post.py + PathScripts/dynapath_post.py + PathScripts/generic_post.py + PathScripts/dumper_post.py + PathScripts/rml_post.py + PathScripts/TooltableEditor.py + PathScripts/PathProfile.py + PathScripts/PathProfileEdges.py PathScripts/PathContour.py - PathScripts/PathCopy.py - PathScripts/PathCustom.py - PathScripts/PathDressup.py - PathScripts/PathDrilling.py - PathScripts/PathEngrave.py - PathScripts/PathFacePocket.py - PathScripts/PathFaceProfile.py - PathScripts/PathFixture.py - PathScripts/PathFromShape.py - PathScripts/PathGeom.py - PathScripts/PathHop.py - PathScripts/PathInspect.py - PathScripts/PathJob.py - PathScripts/PathKurveUtils.py - PathScripts/PathLoadTool.py PathScripts/PathMillFace.py + PathScripts/PathPocket.py + PathScripts/PathDrilling.py + PathScripts/PathDressup.py + PathScripts/DragknifeDressup.py + PathScripts/PathHop.py + PathScripts/PathUtils.py + PathScripts/PathSelection.py + PathScripts/PathFixture.py + PathScripts/PathCopy.py + PathScripts/PathCompoundExtended.py + PathScripts/PathJob.py + PathScripts/PathStock.py PathScripts/PathPlane.py PathScripts/PathPocket.py PathScripts/PathPost.py PathScripts/PathPostProcessor.py - PathScripts/PathPreferences.py - PathScripts/PathPreferencesPathJob.py - PathScripts/PathProfile.py - PathScripts/PathProfileEdges.py - PathScripts/PathRemote.py - PathScripts/PathSanity.py - PathScripts/PathSelection.py - PathScripts/PathSimpleCopy.py - PathScripts/PathStock.py - PathScripts/PathStop.py - PathScripts/PathSurface.py + PathScripts/PathLoadTool.py PathScripts/PathToolLenOffset.py - PathScripts/PathToolLibraryManager.py - PathScripts/PathUtils.py - PathScripts/PostUtils.py - PathScripts/TooltableEditor.py - PathScripts/__init__.py - PathScripts/centroid_post.py - PathScripts/comparams_post.py - PathScripts/dumper_post.py - PathScripts/dynapath_post.py - PathScripts/example_post.py - PathScripts/example_pre.py - PathScripts/generic_post.py - PathScripts/linuxcnc_post.py - PathScripts/opensbp_post.py - PathScripts/opensbp_pre.py - PathScripts/rml_post.py + PathScripts/PathComment.py + PathScripts/PathStop.py + PathScripts/PathFromShape.py + PathScripts/PathKurveUtils.py + PathScripts/PathAreaUtils.py PathScripts/slic3r_pre.py - PathTests/PathTestUtils.py - PathTests/TestPathGeom.py - PathTests/TestPathPost.py + PathScripts/PathFaceProfile.py + PathScripts/PathFacePocket.py + PathScripts/PathArray.py + PathScripts/PathCustom.py + PathScripts/PathInspect.py + PathScripts/PathSimpleCopy.py + PathScripts/PathEngrave.py + PathScripts/PathSurface.py + PathScripts/PathSanity.py + PathScripts/PathToolLibraryManager.py + PathScripts/DogboneDressup.py + PathScripts/PathPreferencesPathJob.py + PathScripts/PathPreferences.py + PathTests/__init__.py PathTests/test_linuxcnc_00.ngc + PathTests/TestPathDepthParams.py + PathTests/TestPathPost.py TestPathApp.py ) diff --git a/src/Mod/Path/Gui/Resources/panels/ToolEdit.ui b/src/Mod/Path/Gui/Resources/panels/ToolEdit.ui index ce7ec3c3df..45a60cb1b8 100644 --- a/src/Mod/Path/Gui/Resources/panels/ToolEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/ToolEdit.ui @@ -6,8 +6,8 @@ 0 0 - 423 - 435 + 361 + 418 @@ -31,7 +31,14 @@ - + + + 50 + + + Display Name + + @@ -42,6 +49,9 @@ + + 6 + Drill @@ -162,6 +172,12 @@ mm + + 0.010000000000000 + + + 5.000000000000000 + @@ -232,6 +248,12 @@ mm + + 0.100000000000000 + + + 10.000000000000000 + diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index 746b4e0716..f252b06fcd 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -356,7 +356,6 @@ class EditorPanel(): pass def getType(self, tooltype): - print("tooltype: ", tooltype) "gets a combobox index number for a given type or viceversa" toolslist = ["Drill", "CenterDrill", "CounterSink", "CounterBore", "Reamer", "Tap", "EndMill", "SlotCutter", "BallEndMill", @@ -389,8 +388,9 @@ class EditorPanel(): def addTool(self): t = Path.Tool() - print (t) + print ("adding a new tool") editform = FreeCADGui.PySideUic.loadUi(":/panels/ToolEdit.ui") + r = editform.exec_() if r: if editform.NameField.text(): From a71e33403bf46a93d53c9d18d5694d6c2d193132 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sun, 11 Dec 2016 12:48:35 -0600 Subject: [PATCH 10/11] Revert "PATH: Prevent Job creation without Base object." This reverts commit fb47372eae783fd9ae110a6d507faa0a79b5051d. --- src/Mod/Path/PathScripts/PathJob.py | 3 --- src/Mod/Path/PathScripts/PathMillFace.py | 5 ----- 2 files changed, 8 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index c22e657ed7..d9cb13aaa3 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -243,9 +243,6 @@ class TaskPanel: self.postProcessorArgsDefaultTooltip = self.form.cboPostProcessorArgs.toolTip() def accept(self): - if self.obj.Base is None: - QtGui.QMessageBox.information(None,"","No Base Object Selected.") - return self.getFields() FreeCADGui.ActiveDocument.resetEdit() FreeCADGui.Control.closeDialog() diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/PathScripts/PathMillFace.py index 3692ced048..d27c1adf5c 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/PathScripts/PathMillFace.py @@ -27,7 +27,6 @@ import Path from PySide import QtCore, QtGui from PathScripts import PathUtils import Part -import PathScripts.PathUtils import PathScripts.PathKurveUtils import area import TechDraw @@ -136,10 +135,6 @@ class ObjectFace: def addFacebase(self, obj, ss, sub=""): - parent = PathScripts.PathUtils.findParentJob(obj) - if parent.Base is None: - return - baselist = obj.Base if baselist is None: baselist = [] From a9130385f410a04c0edbd5d1d6ce1c243f3b3dcb Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sun, 11 Dec 2016 14:11:47 -0600 Subject: [PATCH 11/11] PATH: fix cmake resort --- src/Mod/Path/CMakeLists.txt | 101 +++++++++++++------------ src/Mod/Path/PathTests/TestPathGeom.py | 2 +- src/Mod/Path/TestPathApp.py | 2 +- 3 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 2eb3a902e7..5ba9eac229 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -16,66 +16,67 @@ INSTALL( SET(PathScripts_SRCS PathCommands.py - PathScripts/__init__.py - PathScripts/PostUtils.py - PathScripts/example_pre.py - PathScripts/opensbp_pre.py - PathScripts/opensbp_post.py - PathScripts/example_post.py - PathScripts/linuxcnc_post.py - PathScripts/centroid_post.py - PathScripts/comparams_post.py - PathScripts/dynapath_post.py - PathScripts/generic_post.py - PathScripts/dumper_post.py - PathScripts/rml_post.py - PathScripts/TooltableEditor.py - PathScripts/PathProfile.py - PathScripts/PathProfileEdges.py - PathScripts/PathContour.py - PathScripts/PathMillFace.py - PathScripts/PathPocket.py - PathScripts/PathDrilling.py - PathScripts/PathDressup.py + PathScripts/DogboneDressup.py PathScripts/DragknifeDressup.py - PathScripts/PathHop.py - PathScripts/PathUtils.py - PathScripts/PathSelection.py - PathScripts/PathFixture.py - PathScripts/PathCopy.py + PathScripts/PathAreaUtils.py + PathScripts/PathArray.py + PathScripts/PathComment.py PathScripts/PathCompoundExtended.py + PathScripts/PathContour.py + PathScripts/PathCopy.py + PathScripts/PathCustom.py + PathScripts/PathDressup.py + PathScripts/PathDrilling.py + PathScripts/PathEngrave.py + PathScripts/PathFacePocket.py + PathScripts/PathFaceProfile.py + PathScripts/PathFixture.py + PathScripts/PathFromShape.py + PathScripts/PathGeom.py + PathScripts/PathHop.py + PathScripts/PathInspect.py PathScripts/PathJob.py - PathScripts/PathStock.py + PathScripts/PathKurveUtils.py + PathScripts/PathLoadTool.py + PathScripts/PathMillFace.py PathScripts/PathPlane.py PathScripts/PathPocket.py PathScripts/PathPost.py PathScripts/PathPostProcessor.py - PathScripts/PathLoadTool.py - PathScripts/PathToolLenOffset.py - PathScripts/PathComment.py - PathScripts/PathStop.py - PathScripts/PathFromShape.py - PathScripts/PathKurveUtils.py - PathScripts/PathAreaUtils.py - PathScripts/slic3r_pre.py - PathScripts/PathFaceProfile.py - PathScripts/PathFacePocket.py - PathScripts/PathArray.py - PathScripts/PathCustom.py - PathScripts/PathInspect.py - PathScripts/PathSimpleCopy.py - PathScripts/PathEngrave.py - PathScripts/PathSurface.py - PathScripts/PathSanity.py - PathScripts/PathToolLibraryManager.py - PathScripts/DogboneDressup.py - PathScripts/PathPreferencesPathJob.py PathScripts/PathPreferences.py - + PathScripts/PathPreferencesPathJob.py + PathScripts/PathProfile.py + PathScripts/PathProfileEdges.py + PathScripts/PathSanity.py + PathScripts/PathSelection.py + PathScripts/PathSimpleCopy.py + PathScripts/PathStock.py + PathScripts/PathStop.py + PathScripts/PathSurface.py + PathScripts/PathToolLenOffset.py + PathScripts/PathToolLibraryManager.py + PathScripts/PathUtils.py + PathScripts/PostUtils.py + PathScripts/TooltableEditor.py + PathScripts/__init__.py + PathScripts/centroid_post.py + PathScripts/comparams_post.py + PathScripts/dumper_post.py + PathScripts/dynapath_post.py + PathScripts/example_post.py + PathScripts/example_pre.py + PathScripts/generic_post.py + PathScripts/linuxcnc_post.py + PathScripts/opensbp_post.py + PathScripts/opensbp_pre.py + PathScripts/rml_post.py + PathScripts/slic3r_pre.py + PathTests/PathTestUtils.py + PathTests/TestPathDepthParams.py + PathTests/TestPathGeom.py + PathTests/TestPathPost.py PathTests/__init__.py PathTests/test_linuxcnc_00.ngc - PathTests/TestPathDepthParams.py - PathTests/TestPathPost.py TestPathApp.py ) diff --git a/src/Mod/Path/PathTests/TestPathGeom.py b/src/Mod/Path/PathTests/TestPathGeom.py index 720857bc5d..1b72b7edfd 100644 --- a/src/Mod/Path/PathTests/TestPathGeom.py +++ b/src/Mod/Path/PathTests/TestPathGeom.py @@ -30,7 +30,7 @@ import math import unittest from FreeCAD import Vector -from PathScripts.PathDressupHoldingTags import * +#from PathScripts.PathDressupHoldingTags import * from PathScripts.PathGeom import PathGeom from PathTests.PathTestUtils import PathTestBase diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 82174b3bf3..9886b77d57 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -26,6 +26,6 @@ import TestApp from PathTests.TestPathPost import PathPostTestCases -#from PathTests.TestPathGeom import TestPathGeom +from PathTests.TestPathGeom import TestPathGeom from PathTests.TestPathDepthParams import depthTestCases