OCC pocket handles large curves better now. Needs testing
initial commit
This commit is contained in:
parent
be03c2ad26
commit
a0f332feb0
|
@ -1,31 +1,32 @@
|
|||
#***************************************************************************
|
||||
#* (c) Yorik van Havre (yorik@uncreated.net) 2014 *
|
||||
#* *
|
||||
#* This file is part of the FreeCAD CAx development system. *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* FreeCAD is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Lesser General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with FreeCAD; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************/
|
||||
# ***************************************************************************
|
||||
# * (c) Yorik van Havre (yorik@uncreated.net) 2014 *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * FreeCAD is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Lesser General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with FreeCAD; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************/
|
||||
|
||||
|
||||
class PathWorkbench ( Workbench ):
|
||||
class PathWorkbench (Workbench):
|
||||
"Path workbench"
|
||||
|
||||
def __init__(self):
|
||||
self.__class__.Icon = FreeCAD.getResourceDir() + "Mod/Path/Resources/icons/PathWorkbench.svg"
|
||||
self.__class__.Icon = FreeCAD.getResourceDir(
|
||||
) + "Mod/Path/Resources/icons/PathWorkbench.svg"
|
||||
self.__class__.MenuText = "Path"
|
||||
self.__class__.ToolTip = "Path workbench"
|
||||
|
||||
|
@ -65,59 +66,73 @@ class PathWorkbench ( Workbench ):
|
|||
from PathScripts import PathEngrave
|
||||
from PathScripts import PathSurface
|
||||
from PathScripts import PathRemote
|
||||
from PathScripts import PathSanity
|
||||
|
||||
# build commands list
|
||||
projcmdlist = ["Path_Project", "Path_ToolTableEdit","Path_Post","Path_Inspect"]
|
||||
prepcmdlist = ["Path_Plane","Path_Fixture","Path_LoadTool","Path_ToolLenOffset","Path_Comment","Path_Stop","Path_FaceProfile","Path_FacePocket","Path_Custom","Path_FromShape"]
|
||||
opcmdlist = ["Path_Profile","Path_Pocket","Path_Drilling","Path_Engrave","Path_Surfacing"]
|
||||
modcmdlist = ["Path_Copy","Path_CompoundExtended","Path_Dressup","Path_Hop","Path_Array","Path_SimpleCopy"]
|
||||
projcmdlist = ["Path_Project", "Path_ToolTableEdit",
|
||||
"Path_Post", "Path_Inspect", "Path_Sanity"]
|
||||
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_LoadTool", "Path_ToolLenOffset", "Path_Comment",
|
||||
"Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"]
|
||||
opcmdlist = ["Path_Profile", "Path_Pocket",
|
||||
"Path_Drilling", "Path_Engrave", "Path_Surfacing"]
|
||||
modcmdlist = ["Path_Copy", "Path_CompoundExtended",
|
||||
"Path_Dressup", "Path_Hop", "Path_Array", "Path_SimpleCopy"]
|
||||
remotecmdlist = ["Path_Remote"]
|
||||
|
||||
# Add commands to menu and toolbar
|
||||
def QT_TRANSLATE_NOOP(scope, text):
|
||||
def QT_TRANSLATE_NOOP(scope, text):
|
||||
return text
|
||||
def translate(context,text):
|
||||
return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).encode("utf8")
|
||||
self.appendToolbar(translate("Path","Project Setup"),projcmdlist)
|
||||
self.appendToolbar(translate("Path","Partial Commands"),prepcmdlist)
|
||||
self.appendToolbar(translate("Path","New Operations"),opcmdlist)
|
||||
self.appendToolbar(translate("Path","Path Modification"),modcmdlist)
|
||||
|
||||
self.appendMenu([translate("Path","Path"),translate("Path","Project Setup")],projcmdlist)
|
||||
self.appendMenu([translate("Path","Path"),translate("Path","Partial Commands")],prepcmdlist)
|
||||
self.appendMenu([translate("Path","Path"),translate("Path","New Operations")],opcmdlist)
|
||||
self.appendMenu([translate("Path","Path"),translate("Path","Path Modification")],modcmdlist)
|
||||
self.appendMenu([translate("Path","Path"),translate("Path","Remote Operations")],remotecmdlist)
|
||||
|
||||
def translate(context, text):
|
||||
return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).encode("utf8")
|
||||
self.appendToolbar(translate("Path", "Project Setup"), projcmdlist)
|
||||
self.appendToolbar(translate("Path", "Partial Commands"), prepcmdlist)
|
||||
self.appendToolbar(translate("Path", "New Operations"), opcmdlist)
|
||||
self.appendToolbar(translate("Path", "Path Modification"), modcmdlist)
|
||||
|
||||
self.appendMenu([translate("Path", "Path"), translate(
|
||||
"Path", "Project Setup")], projcmdlist)
|
||||
self.appendMenu([translate("Path", "Path"), translate(
|
||||
"Path", "Partial Commands")], prepcmdlist)
|
||||
self.appendMenu([translate("Path", "Path"), translate(
|
||||
"Path", "New Operations")], opcmdlist)
|
||||
self.appendMenu([translate("Path", "Path"), translate(
|
||||
"Path", "Path Modification")], modcmdlist)
|
||||
self.appendMenu([translate("Path", "Path"), translate(
|
||||
"Path", "Remote Operations")], remotecmdlist)
|
||||
|
||||
# Add preferences pages
|
||||
import os
|
||||
FreeCADGui.addPreferencePage(FreeCAD.getHomePath()+os.sep+"Mod"+os.sep+"Path"+os.sep+"PathScripts"+os.sep+"DlgSettingsPath.ui","Path")
|
||||
|
||||
Log ('Loading Path workbench... done\n')
|
||||
FreeCADGui.addPreferencePage(FreeCAD.getHomePath(
|
||||
) + os.sep + "Mod" + os.sep + "Path" + os.sep + "PathScripts" + os.sep + "DlgSettingsPath.ui", "Path")
|
||||
|
||||
Log('Loading Path workbench... done\n')
|
||||
|
||||
def GetClassName(self):
|
||||
return "Gui::PythonWorkbench"
|
||||
|
||||
|
||||
def Activated(self):
|
||||
# update the translation engine
|
||||
FreeCADGui.updateLocale()
|
||||
Msg("Path workbench activated\n")
|
||||
|
||||
|
||||
def Deactivated(self):
|
||||
Msg("Path workbench deactivated\n")
|
||||
|
||||
|
||||
def ContextMenu(self, recipient):
|
||||
if len(FreeCADGui.Selection.getSelection()) == 1:
|
||||
if FreeCADGui.Selection.getSelection()[0].isDerivedFrom("Path::Feature"):
|
||||
self.appendContextMenu("",["Path_Inspect"])
|
||||
if "Profile" in FreeCADGui.Selection.getSelection()[0].Name:
|
||||
self.appendContextMenu("",["Add_Tag"])
|
||||
self.appendContextMenu("",["Set_StartPoint"])
|
||||
self.appendContextMenu("",["Set_EndPoint"])
|
||||
if "Remote" in FreeCADGui.Selection.getSelection()[0].Name:
|
||||
self.appendContextMenu("",["Refresh_Path"])
|
||||
self.appendContextMenu("", ["Path_Inspect"])
|
||||
if "Profile" in FreeCADGui.Selection.getSelection()[0].Name:
|
||||
self.appendContextMenu("", ["Add_Tag"])
|
||||
self.appendContextMenu("", ["Set_StartPoint"])
|
||||
self.appendContextMenu("", ["Set_EndPoint"])
|
||||
if "Remote" in FreeCADGui.Selection.getSelection()[0].Name:
|
||||
self.appendContextMenu("", ["Refresh_Path"])
|
||||
|
||||
Gui.addWorkbench(PathWorkbench())
|
||||
|
||||
FreeCAD.addImportType("GCode (*.nc *.gc *.ncc *.ngc *.cnc *.tap *.gcode)","PathGui")
|
||||
FreeCAD.addExportType("GCode (*.nc *.gc *.ncc *.ngc *.cnc *.tap *.gcode)","PathGui")
|
||||
FreeCAD.addImportType(
|
||||
"GCode (*.nc *.gc *.ncc *.ngc *.cnc *.tap *.gcode)", "PathGui")
|
||||
FreeCAD.addExportType(
|
||||
"GCode (*.nc *.gc *.ncc *.ngc *.cnc *.tap *.gcode)", "PathGui")
|
||||
|
|
|
@ -74,7 +74,7 @@ class ObjectDrilling:
|
|||
def execute(self, obj):
|
||||
output = ""
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad is None:
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.radius = 0.25
|
||||
|
|
|
@ -80,7 +80,7 @@ class ObjectPathEngrave:
|
|||
output = ""
|
||||
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad is None:
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.radius = 0.25
|
||||
|
|
|
@ -1,79 +1,99 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
|
||||
#* *
|
||||
#* 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 *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
|
||||
# * *
|
||||
# * 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
''' A CNC machine object to define how code is posted '''
|
||||
|
||||
import FreeCAD,Path
|
||||
import FreeCAD
|
||||
import Path
|
||||
import PathScripts
|
||||
from PathScripts import PathProject, PathUtils
|
||||
from PySide import QtCore,QtGui
|
||||
import os, sys
|
||||
from PathScripts import PathUtils
|
||||
from PySide import QtCore, QtGui
|
||||
import os
|
||||
import sys
|
||||
|
||||
# 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 Machine:
|
||||
def __init__(self,obj):
|
||||
|
||||
obj.addProperty("App::PropertyString", "MachineName","Base",translate("Machine Name","Name of the Machine that will use the CNC program"))
|
||||
def __init__(self, obj):
|
||||
|
||||
obj.addProperty("App::PropertyFile", "PostProcessor", "CodeOutput", translate("Post Processor","Select the Post Processor file for this machine"))
|
||||
#obj.setEditorMode("PostProcessor",1) #set to read only
|
||||
obj.addProperty("App::PropertyEnumeration", "MachineUnits","CodeOutput", translate( "Machine Units", "Units that the machine works in, ie Metric or Inch"))
|
||||
obj.MachineUnits=['Metric', 'Inch']
|
||||
obj.addProperty("App::PropertyString", "MachineName", "Base", translate(
|
||||
"Machine Name", "Name of the Machine that will use the CNC program"))
|
||||
|
||||
obj.addProperty("Path::PropertyTooltable","Tooltable", "Base",translate("Tool Table","The tooltable used for this CNC program"))
|
||||
obj.addProperty("App::PropertyFile", "PostProcessor", "CodeOutput", translate(
|
||||
"Post Processor", "Select the Post Processor file for this machine"))
|
||||
# obj.setEditorMode("PostProcessor",1) #set to read only
|
||||
obj.addProperty("App::PropertyEnumeration", "MachineUnits", "CodeOutput", translate(
|
||||
"Machine Units", "Units that the machine works in, ie Metric or Inch"))
|
||||
obj.MachineUnits = ['Metric', 'Inch']
|
||||
|
||||
obj.addProperty("App::PropertyDistance", "X_Max", "Limits", translate("X Maximum Limit","The Maximum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Y_Max", "Limits", translate("Y Maximum Limit","The Maximum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Z_Max", "Limits", translate("Y Maximum Limit","The Maximum distance in X the machine can travel"))
|
||||
obj.addProperty("Path::PropertyTooltable", "Tooltable", "Base", translate(
|
||||
"Tool Table", "The tooltable used for this CNC program"))
|
||||
|
||||
obj.addProperty("App::PropertyDistance", "X_Min", "Limits", translate("X Minimum Limit","The Minimum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Y_Min", "Limits", translate("Y Minimum Limit","The Minimum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Z_Min", "Limits", translate("Y Minimum Limit","The Minimum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "X_Max", "Limits", translate(
|
||||
"X Maximum Limit", "The Maximum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Y_Max", "Limits", translate(
|
||||
"Y Maximum Limit", "The Maximum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Z_Max", "Limits", translate(
|
||||
"Y Maximum Limit", "The Maximum distance in X the machine can travel"))
|
||||
|
||||
obj.addProperty("App::PropertyDistance", "X", "HomePosition", translate("X Home Position","Home position of machine, in X (mainly for visualization)"))
|
||||
obj.addProperty("App::PropertyDistance", "Y", "HomePosition", translate("Y Home Position","Home position of machine, in Y (mainly for visualization)"))
|
||||
obj.addProperty("App::PropertyDistance", "Z", "HomePosition", translate("Z Home Position","Home position of machine, in Z (mainly for visualization)"))
|
||||
obj.addProperty("App::PropertyDistance", "X_Min", "Limits", translate(
|
||||
"X Minimum Limit", "The Minimum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Y_Min", "Limits", translate(
|
||||
"Y Minimum Limit", "The Minimum distance in X the machine can travel"))
|
||||
obj.addProperty("App::PropertyDistance", "Z_Min", "Limits", translate(
|
||||
"Y Minimum Limit", "The Minimum distance in X the machine can travel"))
|
||||
|
||||
obj.addProperty("App::PropertyDistance", "X", "HomePosition", translate(
|
||||
"X Home Position", "Home position of machine, in X (mainly for visualization)"))
|
||||
obj.addProperty("App::PropertyDistance", "Y", "HomePosition", translate(
|
||||
"Y Home Position", "Home position of machine, in Y (mainly for visualization)"))
|
||||
obj.addProperty("App::PropertyDistance", "Z", "HomePosition", translate(
|
||||
"Z Home Position", "Home position of machine, in Z (mainly for visualization)"))
|
||||
|
||||
obj.Proxy = self
|
||||
mode = 2
|
||||
obj.setEditorMode('Placement',mode)
|
||||
obj.setEditorMode('Placement', mode)
|
||||
|
||||
def execute(self,obj):
|
||||
obj.Label = "Machine_"+str(obj.MachineName)
|
||||
gcode = 'G0 X'+str(obj.X.Value)+' Y'+str(obj.Y.Value)+' Z'+str(obj.Z.Value) #need to filter this path out in post- only for visualization
|
||||
def execute(self, obj):
|
||||
obj.Label = "Machine_" + str(obj.MachineName)
|
||||
# need to filter this path out in post- only for visualization
|
||||
gcode = 'G0 X' + str(obj.X.Value) + ' Y' + \
|
||||
str(obj.Y.Value) + ' Z' + str(obj.Z.Value)
|
||||
obj.Path = Path.Path(gcode)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
def onChanged(self, obj, prop):
|
||||
mode = 2
|
||||
obj.setEditorMode('Placement',mode)
|
||||
obj.setEditorMode('Placement', mode)
|
||||
|
||||
if prop == "PostProcessor":
|
||||
sys.path.append(os.path.split(obj.PostProcessor)[0])
|
||||
|
@ -81,161 +101,167 @@ class Machine:
|
|||
postname = os.path.split(lessextn)[1]
|
||||
|
||||
exec "import %s as current_post" % postname
|
||||
if hasattr (current_post, "UNITS"):
|
||||
if hasattr(current_post, "UNITS"):
|
||||
if current_post.UNITS == "G21":
|
||||
obj.MachineUnits = "Metric"
|
||||
else:
|
||||
obj.MachineUnits = "Inch"
|
||||
if hasattr (current_post, "MACHINE_NAME"): obj.MachineName = current_post.MACHINE_NAME
|
||||
if hasattr(current_post, "MACHINE_NAME"):
|
||||
obj.MachineName = current_post.MACHINE_NAME
|
||||
|
||||
if hasattr (current_post, "CORNER_MAX"):
|
||||
if hasattr(current_post, "CORNER_MAX"):
|
||||
obj.X_Max = current_post.CORNER_MAX['x']
|
||||
obj.Y_Max = current_post.CORNER_MAX['y']
|
||||
obj.Z_Max = current_post.CORNER_MAX['z']
|
||||
|
||||
if hasattr (current_post, "CORNER_MIN"):
|
||||
if hasattr(current_post, "CORNER_MIN"):
|
||||
obj.X_Min = current_post.CORNER_MIN['x']
|
||||
obj.Y_Min = current_post.CORNER_MIN['y']
|
||||
obj.Z_Min = current_post.CORNER_MIN['z']
|
||||
|
||||
if prop == "Tooltable":
|
||||
proj = PathUtils.findProj()
|
||||
proj = PathUtils.findProj()
|
||||
for g in proj.Group:
|
||||
if not(isinstance(g.Proxy, PathScripts.PathMachine.Machine)):
|
||||
g.touch()
|
||||
|
||||
|
||||
|
||||
class _ViewProviderMachine:
|
||||
def __init__(self,vobj):
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
vobj.addProperty("App::PropertyBool","ShowLimits","Path","Switch the machine max and minimum travel bounding box on/off")
|
||||
vobj.addProperty("App::PropertyBool", "ShowLimits", "Path", translate(
|
||||
"ShowMinMaxTravel", "Switch the machine max and minimum travel bounding box on/off"))
|
||||
mode = 2
|
||||
vobj.setEditorMode('LineWidth',mode)
|
||||
vobj.setEditorMode('MarkerColor',mode)
|
||||
vobj.setEditorMode('NormalColor',mode)
|
||||
vobj.setEditorMode('ShowFirstRapid',0)
|
||||
vobj.setEditorMode('DisplayMode',mode)
|
||||
vobj.setEditorMode('BoundingBox',mode)
|
||||
vobj.setEditorMode('Selectable',mode)
|
||||
|
||||
|
||||
def __getstate__(self): #mandatory
|
||||
vobj.setEditorMode('LineWidth', mode)
|
||||
vobj.setEditorMode('MarkerColor', mode)
|
||||
vobj.setEditorMode('NormalColor', mode)
|
||||
vobj.setEditorMode('ShowFirstRapid', 0)
|
||||
vobj.setEditorMode('DisplayMode', mode)
|
||||
vobj.setEditorMode('BoundingBox', mode)
|
||||
vobj.setEditorMode('Selectable', mode)
|
||||
|
||||
def __getstate__(self): # mandatory
|
||||
return None
|
||||
|
||||
def __setstate__(self,state): #mandatory
|
||||
def __setstate__(self, state): # mandatory
|
||||
return None
|
||||
|
||||
def getIcon(self): #optional
|
||||
def getIcon(self): # optional
|
||||
return ":/icons/Path-Machine.svg"
|
||||
|
||||
def attach(self,vobj):
|
||||
def attach(self, vobj):
|
||||
from pivy import coin
|
||||
self.extentsBox = coin.SoSeparator()
|
||||
vobj.RootNode.addChild(self.extentsBox)
|
||||
|
||||
def onChanged(self,vobj,prop):
|
||||
|
||||
def onChanged(self, vobj, prop):
|
||||
|
||||
if prop == "ShowLimits":
|
||||
self.extentsBox.removeAllChildren()
|
||||
if vobj.ShowLimits and hasattr(vobj,"Object"):
|
||||
if vobj.ShowLimits and hasattr(vobj, "Object"):
|
||||
from pivy import coin
|
||||
parent = coin.SoType.fromName("SoSkipBoundingGroup").createInstance()
|
||||
parent = coin.SoType.fromName(
|
||||
"SoSkipBoundingGroup").createInstance()
|
||||
self.extentsBox.addChild(parent)
|
||||
# set pattern
|
||||
pattern = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Part").GetInt("GridLinePattern",0x0f0f)
|
||||
pattern = FreeCAD.ParamGet(
|
||||
"User parameter:BaseApp/Preferences/Mod/Part").GetInt("GridLinePattern", 0x0f0f)
|
||||
defStyle = coin.SoDrawStyle()
|
||||
defStyle.lineWidth = 1
|
||||
defStyle.linePattern = pattern
|
||||
parent.addChild(defStyle)
|
||||
# set color
|
||||
c = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path").GetUnsigned("DefaultExtentsColor",3418866943)
|
||||
r = float((c>>24)&0xFF)/255.0
|
||||
g = float((c>>16)&0xFF)/255.0
|
||||
b = float((c>>8)&0xFF)/255.0
|
||||
c = FreeCAD.ParamGet(
|
||||
"User parameter:BaseApp/Preferences/Mod/Path").GetUnsigned("DefaultExtentsColor", 3418866943)
|
||||
r = float((c >> 24) & 0xFF) / 255.0
|
||||
g = float((c >> 16) & 0xFF) / 255.0
|
||||
b = float((c >> 8) & 0xFF) / 255.0
|
||||
color = coin.SoBaseColor()
|
||||
parent.addChild(color)
|
||||
# set boundbox
|
||||
extents = coin.SoType.fromName("SoFCBoundingBox").createInstance()
|
||||
extents = coin.SoType.fromName(
|
||||
"SoFCBoundingBox").createInstance()
|
||||
extents.coordsOn.setValue(False)
|
||||
extents.dimensionsOn.setValue(False)
|
||||
|
||||
XMax, YMax, ZMax =vobj.Object.X_Max.Value , vobj.Object.Y_Max.Value , vobj.Object.Z_Max.Value
|
||||
XMin, YMin, ZMin =vobj.Object.X_Min.Value , vobj.Object.Y_Min.Value , vobj.Object.Z_Min.Value
|
||||
UnitParams = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units")
|
||||
XMax, YMax, ZMax = vobj.Object.X_Max.Value, vobj.Object.Y_Max.Value, vobj.Object.Z_Max.Value
|
||||
XMin, YMin, ZMin = vobj.Object.X_Min.Value, vobj.Object.Y_Min.Value, vobj.Object.Z_Min.Value
|
||||
# UnitParams = FreeCAD.ParamGet(
|
||||
# "User parameter:BaseApp/Preferences/Units")
|
||||
|
||||
extents.minBounds.setValue(XMax, YMax, ZMax)
|
||||
extents.maxBounds.setValue(XMin, YMin, ZMin)
|
||||
|
||||
parent.addChild(extents)
|
||||
mode = 2
|
||||
vobj.setEditorMode('LineWidth',mode)
|
||||
vobj.setEditorMode('MarkerColor',mode)
|
||||
vobj.setEditorMode('NormalColor',mode)
|
||||
vobj.setEditorMode('ShowFirstRapid',0)
|
||||
vobj.setEditorMode('DisplayMode',mode)
|
||||
vobj.setEditorMode('BoundingBox',mode)
|
||||
vobj.setEditorMode('Selectable',mode)
|
||||
vobj.setEditorMode('LineWidth', mode)
|
||||
vobj.setEditorMode('MarkerColor', mode)
|
||||
vobj.setEditorMode('NormalColor', mode)
|
||||
vobj.setEditorMode('ShowFirstRapid', 0)
|
||||
vobj.setEditorMode('DisplayMode', mode)
|
||||
vobj.setEditorMode('BoundingBox', mode)
|
||||
vobj.setEditorMode('Selectable', mode)
|
||||
|
||||
|
||||
|
||||
|
||||
def updateData(self,vobj,prop): #optional
|
||||
def updateData(self, vobj, prop): # optional
|
||||
# this is executed when a property of the APP OBJECT changes
|
||||
pass
|
||||
|
||||
def setEdit(self,vobj,mode=0): #optional
|
||||
def setEdit(self, vobj, mode=0): # optional
|
||||
# this is executed when the object is double-clicked in the tree
|
||||
pass
|
||||
|
||||
def unsetEdit(self,vobj,mode=0): #optional
|
||||
def unsetEdit(self, vobj, mode=0): # optional
|
||||
# this is executed when the user cancels or terminates edit mode
|
||||
pass
|
||||
|
||||
def doubleClicked(self,vobj):
|
||||
|
||||
def doubleClicked(self, vobj):
|
||||
from PathScripts import TooltableEditor
|
||||
TooltableEditor.edit(vobj.Object.Name)
|
||||
|
||||
|
||||
class CommandPathMachine:
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Path-Machine',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathMachine","Machine Object"),
|
||||
return {'Pixmap': 'Path-Machine',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathMachine", "Machine Object"),
|
||||
'Accel': "P, M",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathMachine","Create a Machine object")}
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathMachine", "Create a Machine object")}
|
||||
|
||||
def IsActive(self):
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
return FreeCAD.ActiveDocument is not None
|
||||
|
||||
def Activated(self):
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("PathMachine","Create a Machine object"))
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
translate("PathMachine", "Create a Machine object"))
|
||||
CommandPathMachine.Create()
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
@staticmethod
|
||||
def Create():
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Machine")
|
||||
obj = FreeCAD.ActiveDocument.addObject(
|
||||
"Path::FeaturePython", "Machine")
|
||||
Machine(obj)
|
||||
_ViewProviderMachine(obj.ViewObject)
|
||||
|
||||
PathUtils.addToProject(obj)
|
||||
|
||||
UnitParams = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units")
|
||||
UnitParams = FreeCAD.ParamGet(
|
||||
"User parameter:BaseApp/Preferences/Units")
|
||||
if UnitParams.GetInt('UserSchema') == 0:
|
||||
obj.MachineUnits = 'Metric'
|
||||
#metric mode
|
||||
# metric mode
|
||||
else:
|
||||
obj.MachineUnits = 'Inch'
|
||||
|
||||
obj.ViewObject.ShowFirstRapid = False
|
||||
return obj
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
import FreeCADGui
|
||||
FreeCADGui.addCommand('Path_Machine',CommandPathMachine())
|
||||
FreeCADGui.addCommand('Path_Machine', CommandPathMachine())
|
||||
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathMachine... done\n")
|
||||
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ class ObjectPocket:
|
|||
obj.addProperty("App::PropertyDistance", "MaterialAllowance", "Pocket", translate("PathProject", "Amount of material to leave"))
|
||||
obj.addProperty("App::PropertyEnumeration", "StartAt", "Pocket", translate("PathProject", "Start pocketing at center or boundary"))
|
||||
obj.StartAt = ['Center', 'Edge']
|
||||
obj.addProperty("App::PropertyFloatConstraint", "StepOver", "Pocket", translate("PathProject", "Amount to step over on each pass"))
|
||||
obj.StepOver = (0.0, 0.01, 100.0, 0.5)
|
||||
obj.addProperty("App::PropertyPercent", "StepOver", "Pocket", translate("PathProject", "Percent of cutter diameter to step over on each pass"))
|
||||
#obj.StepOver = (0.0, 0.01, 100.0, 0.5)
|
||||
obj.addProperty("App::PropertyBool", "KeepToolDown", "Pocket", translate("PathProject", "Attempts to avoid unnecessary retractions."))
|
||||
obj.addProperty("App::PropertyBool", "ZigUnidirectional", "Pocket", translate("PathProject", "Lifts tool at the end of each pass to respect cut mode."))
|
||||
obj.addProperty("App::PropertyBool", "UseZigZag", "Pocket", translate("PathProject", "Use Zig Zag pattern to clear area."))
|
||||
|
@ -118,22 +118,7 @@ class ObjectPocket:
|
|||
if baselist is None:
|
||||
baselist = []
|
||||
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
|
||||
|
||||
try:
|
||||
bb = ss.Shape.BoundBox # parent boundbox
|
||||
|
@ -197,7 +182,7 @@ class ObjectPocket:
|
|||
obj.FinalDepth.Value)
|
||||
|
||||
extraoffset = obj.MaterialAllowance.Value
|
||||
stepover = obj.StepOver
|
||||
stepover = (self.radius * 2) * (float(obj.StepOver)/100)
|
||||
use_zig_zag = obj.UseZigZag
|
||||
zig_angle = obj.ZigZagAngle
|
||||
from_center = (obj.StartAt == "Center")
|
||||
|
@ -242,22 +227,23 @@ class ObjectPocket:
|
|||
# Build up the offset loops
|
||||
output = ""
|
||||
offsets = []
|
||||
nextradius = self.radius
|
||||
nextradius = (self.radius * 2) * (float(obj.StepOver)/100)
|
||||
result = DraftGeomUtils.pocket2d(shape, nextradius)
|
||||
print "did we get something: " + str(result)
|
||||
while result:
|
||||
print "Adding " + str(len(result)) + " wires"
|
||||
offsets.extend(result)
|
||||
nextradius += self.radius
|
||||
nextradius += (self.radius * 2) * (float(obj.StepOver)/100)
|
||||
result = DraftGeomUtils.pocket2d(shape, nextradius)
|
||||
|
||||
# revert the list so we start with the outer wires
|
||||
if obj.StartAt != 'Edge':
|
||||
offsets.reverse()
|
||||
|
||||
plungePos = None
|
||||
rampEdge = None
|
||||
if obj.UseEntry:
|
||||
# Try to find an entry location
|
||||
plungePos = None
|
||||
toold = self.radius*2
|
||||
helixBounds = DraftGeomUtils.pocket2d(shape, self.radius * (1 + obj.HelixSize))
|
||||
|
||||
|
@ -279,7 +265,6 @@ class ObjectPocket:
|
|||
# Maybe reverse helixBounds and pick off that?
|
||||
|
||||
if plungePos is None: # If we didn't find a place to helix, how about a ramp?
|
||||
rampEdge = None
|
||||
FreeCAD.Console.PrintMessage(translate("PathPocket", "Attempting ramp entry.\n"))
|
||||
if (offsets[0].Edges[0].Length >= toold * rampD) and not (isinstance(offsets[0].Edges[0].Curve, Part.Circle)):
|
||||
rampEdge = offsets[0].Edges[0]
|
||||
|
@ -305,6 +290,7 @@ class ObjectPocket:
|
|||
first = True
|
||||
# loop over successive wires
|
||||
for currentWire in offsets:
|
||||
#output += PathUtils.convert(currentWire.Edges, "on", 1)
|
||||
last = None
|
||||
for edge in currentWire.Edges:
|
||||
if not last:
|
||||
|
@ -363,7 +349,7 @@ class ObjectPocket:
|
|||
def execute(self, obj):
|
||||
output = ""
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad is None:
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.radius = 0.25
|
||||
|
@ -371,13 +357,14 @@ class ObjectPocket:
|
|||
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
|
||||
|
||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
||||
if tool is None:
|
||||
self.radius = 0.25
|
||||
else:
|
||||
self.radius = tool.Diameter/2
|
||||
# if tool is None:
|
||||
# self.radius = 0.25
|
||||
# else:
|
||||
# self.radius = tool.Diameter/2
|
||||
|
||||
if obj.Base:
|
||||
for b in obj.Base:
|
||||
|
@ -514,7 +501,7 @@ class CommandPathPocket:
|
|||
FreeCADGui.doCommand('obj.Active = True')
|
||||
FreeCADGui.doCommand('PathScripts.PathPocket.ViewProviderPocket(obj.ViewObject)')
|
||||
FreeCADGui.doCommand('from PathScripts import PathUtils')
|
||||
FreeCADGui.doCommand('obj.StepOver = 1.0')
|
||||
FreeCADGui.doCommand('obj.StepOver = 100')
|
||||
FreeCADGui.doCommand('obj.ClearanceHeight = 10') # + str(bb.ZMax + 2.0))
|
||||
FreeCADGui.doCommand('obj.StepDown = 1.0')
|
||||
FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop))
|
||||
|
|
|
@ -258,7 +258,7 @@ print "y - " + str(point.y)
|
|||
import Part # math #DraftGeomUtils
|
||||
output = ""
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad is None:
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.radius = 0.25
|
||||
|
|
|
@ -157,7 +157,7 @@ class ObjectRemote:
|
|||
output = ""
|
||||
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad is None:
|
||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.radius = 0.25
|
||||
|
|
100
src/Mod/Path/PathScripts/PathSanity.py
Normal file
100
src/Mod/Path/PathScripts/PathSanity.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
# ***************************************************************************
|
||||
# * (c) Sliptonic (shopinthewoods@gmail.com) 2016 *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * FreeCAD is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Lesser General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with FreeCAD; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************/
|
||||
|
||||
'''This file has utilities for checking and catching common errors in FreeCAD
|
||||
Path projects. Ideally, the user could execute these utilities from an icon
|
||||
to make sure tools are selected and configured and defaults have been revised'''
|
||||
|
||||
from PySide import QtCore, QtGui
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import PathScripts.PathUtils as PU
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
def review(obj):
|
||||
|
||||
"checks the selected project for common errors"
|
||||
for item in obj.Group:
|
||||
print "Checking: " + item.Label
|
||||
|
||||
if item.Name[:4] == "Tool":
|
||||
if item.ToolNumber == 0:
|
||||
FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using ID 0 which is the default\n"))
|
||||
else:
|
||||
tool = PU.getTool(item, item.ToolNumber)
|
||||
if tool is None:
|
||||
FreeCAD.Console.PrintError(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using tool: " + str(item.ToolNumber) + " which is invalid\n"))
|
||||
continue
|
||||
|
||||
if tool.Diameter == 0:
|
||||
FreeCAD.Console.PrintError(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using tool: " + str(item.ToolNumber) + " which has a zero diameter\n"))
|
||||
if item.HorizFeed == 0:
|
||||
FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " has a 0 value for the Horizontal feed rate\n"))
|
||||
if item.VertFeed == 0:
|
||||
FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " has a 0 value for the Vertical feed rate\n"))
|
||||
if item.SpindleSpeed == 0:
|
||||
FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " has a 0 value for the spindle speed\n"))
|
||||
|
||||
if item.Name[:7] == "Machine":
|
||||
if len(item.Tooltable.Tools) == 0:
|
||||
FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Machine: " + str(item.Label) + " has no tools defined in the tool table\n"))
|
||||
|
||||
|
||||
class CommandPathSanity:
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Path-Sanity',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Sanity","Check the Path project for common errors"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Sanity","Check the Path Project for common errors")}
|
||||
|
||||
def IsActive(self):
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
|
||||
def Activated(self):
|
||||
# check that the selection contains exactly what we want
|
||||
selection = FreeCADGui.Selection.getSelection()
|
||||
if len(selection) != 1:
|
||||
FreeCAD.Console.PrintError(translate("Path_Sanity","Please select a path Project to check\n"))
|
||||
return
|
||||
if not(selection[0].TypeId == "Path::FeatureCompoundPython"):
|
||||
FreeCAD.Console.PrintError(translate("Path_Sanity","Please select a path project to check\n"))
|
||||
return
|
||||
|
||||
# if everything is ok, execute
|
||||
FreeCADGui.addModule("PathScripts.PathSanity")
|
||||
FreeCADGui.doCommand('PathScripts.PathSanity.review(FreeCAD.ActiveDocument.' + selection[0].Name + ')')
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
FreeCADGui.addCommand('Path_Sanity',CommandPathSanity())
|
||||
|
|
@ -241,7 +241,7 @@ class ObjectSurface:
|
|||
output = ""
|
||||
|
||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
||||
if toolLoad == None:
|
||||
if toolLoad == None or toolLoad.ToolNumber == 0:
|
||||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.radius = 0.25
|
||||
|
|
|
@ -26,6 +26,7 @@ import FreeCAD
|
|||
import Part
|
||||
import math
|
||||
from DraftGeomUtils import geomType
|
||||
from DraftGeomUtils import findWires
|
||||
import DraftVecUtils
|
||||
import PathScripts
|
||||
from PathScripts import PathProject
|
||||
|
@ -271,9 +272,11 @@ def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
|
|||
|
||||
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:
|
||||
|
@ -287,7 +290,9 @@ def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
|
|||
geomType(e) == "BezierCurve" or \
|
||||
geomType(e) == "Ellipse":
|
||||
edgelist.append(Part.Wire(curvetowire(e, (SegLen))))
|
||||
newwire = Part.Wire(edgelist)
|
||||
#newwire = Part.Wire(edgelist)
|
||||
sortededges = Part.__sortEdges__(edgelist)
|
||||
newwire = findWires(sortededges)[0]
|
||||
|
||||
if Side == 'Left':
|
||||
# we use the OCC offset feature
|
||||
|
|
Loading…
Reference in New Issue
Block a user