PATH: Delete misplaced and unused files

This commit is contained in:
sliptonic 2016-11-17 10:16:41 -06:00
parent 207432c0bd
commit 84b3617c97
20 changed files with 385 additions and 2674 deletions

View File

@ -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

View File

@ -1,145 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>946</width>
<height>614</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCommandLinkButton" name="cmdAddTools">
<property name="text">
<string>Add Selected Tools to Project</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Tool Library</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="2">
<widget class="QPushButton" name="ButtonDelete">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="ButtonImport">
<property name="text">
<string>Import...</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QPushButton" name="ButtonUp">
<property name="text">
<string>Move up</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="ButtonAdd">
<property name="text">
<string>Add new List</string>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="ButtonDown">
<property name="text">
<string>Move down</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="ButtonNewTool">
<property name="text">
<string>New Tool</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QListWidget" name="listWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="ButtonExport">
<property name="text">
<string>Export...</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4">
<widget class="QTableView" name="ToolsList"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,244 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>807</width>
<height>555</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Tool Properties</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="NameField"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="TypeField"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="MaterialField"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="DiameterField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Length Offset</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QDoubleSpinBox" name="LengthOffsetField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Flat Radius</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QDoubleSpinBox" name="FlatRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Corner Radius</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QDoubleSpinBox" name="CornerRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cutting Edge Angle</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeAngleField">
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cutting Edge Height</string>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeHeightField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Tool List</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="1">
<widget class="QPushButton" name="ButtonDelete">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="ButtonUp">
<property name="text">
<string>Move up</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QPushButton" name="ButtonImport">
<property name="text">
<string>Import...</string>
</property>
</widget>
</item>
<item row="0" column="2" colspan="2">
<widget class="QPushButton" name="ButtonExport">
<property name="text">
<string>Export...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="ButtonAdd">
<property name="text">
<string>Add new</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QTableView" name="ToolsList"/>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="ButtonDown">
<property name="text">
<string>Move down</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -1,478 +0,0 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2016 sliptonic <shopinthewoods@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 *
# * *
# ***************************************************************************
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")

View File

@ -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():

View File

@ -1,401 +0,0 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2016 sliptonic <shopinthewoods@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 *
# * *
# ***************************************************************************
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")

View File

@ -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):

View File

@ -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."""

View File

@ -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'''

View File

@ -1,190 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>423</width>
<height>435</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Tool Properties</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="NameField"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="TypeField"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="MaterialField"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="DiameterField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Length Offset</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QDoubleSpinBox" name="LengthOffsetField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Flat Radius</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QDoubleSpinBox" name="FlatRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Corner Radius</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QDoubleSpinBox" name="CornerRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cutting Edge Angle</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeAngleField_2">
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cutting Edge Height</string>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeHeightField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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"

View File

@ -1,242 +0,0 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 sliptonic <shopinthewoods@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 *
# * *
# ***************************************************************************
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